Merge cand's graphical improvements branch!! There are many known issues folks, so don't cry victory just now, this is just the beginning. Especially, shadows do not work correctly at this time

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14590 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2013-11-30 21:33:06 +00:00
parent 8c17d21282
commit 5899a26aad
157 changed files with 8699 additions and 1440 deletions

View File

@ -9,7 +9,7 @@
y="-0.01"
z="0.0" />
<material file="snowflake.png"/>
<material file="snowflake.png" clampu="Y" clampv="Y" />
<!-- Amount of particles emitted per second -->
<rate min="400"
@ -23,10 +23,13 @@
<size min="0.40"
max="0.60" />
<color min="255 255 255"
<color min="40 40 255"
max="255 255 255" />
<!-- How much time in milliseconds before the particle is fully faded out -->
<fadeout time="100" />
<wind speed="0.16"
flips="Y" />
</particles>

View File

@ -1,18 +1,33 @@
<stkgui>
<div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" >
<div x="2%" y="5%" width="96%" height="95%" layout="vertical-row" >
<header id="title" width="100%" height="fit" text_align="center" word_wrap="true" text="Graphics Settings" />
<spacer height="25" width="10" />
<spacer height="20" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<checkbox id="pixelshaders"/>
<spacer width="10" height="10"/>
<label text="Pixel Shaders (requires restart)" I18N="Video settings"/>
</div>
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<checkbox id="anim_gfx"/>
<spacer width="10" height="10"/>
<label text="Animated Scenery" I18N="Video settings"/>
<spacer width="20%" height="10"/>
<checkbox id="motionblur"/>
<spacer width="10" height="10"/>
<label text="Motion blur" I18N="Video settings"/>
</div>
<spacer height="5" width="10" />
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<checkbox id="weather_gfx"/>
@ -20,7 +35,7 @@
<label text="Weather Effects" I18N="Video settings"/>
</div>
<spacer height="5" width="10" />
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<label text="Animated Characters" I18N="Video settings" width="40%"/>
@ -28,7 +43,7 @@
<gauge id="steering_animations" min_value="0" max_value="2" width="50%" />
</div>
<spacer height="5" width="10" />
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<label text="Texture filtering" I18N="Video settings" width="40%"/>
@ -36,7 +51,7 @@
<gauge id="filtering" min_value="0" max_value="5" width="50%" />
</div>
<spacer height="5" width="10" />
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<label text="Anti-aliasing (requires restart)" I18N="Video settings" width="40%" />
@ -44,20 +59,28 @@
<gauge id="antialiasing" min_value="0" max_value="3" width="50%"/>
</div>
<spacer height="5" width="10" />
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<checkbox id="postprocessing"/>
<checkbox id="mlaa"/>
<spacer width="10" height="10"/>
<label text="Post-processing (motion blur)" I18N="Video settings"/>
<label text="MLAA (morphological anti-aliasing)" I18N="Video settings"/>
</div>
<spacer height="5" width="10" />
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<checkbox id="pixelshaders"/>
<label text="SSAO (Ambient Occlusion, requires restart)" I18N="Video settings"/>
<spacer width="10" height="10"/>
<label text="Pixel Shaders" I18N="Video settings"/>
<gauge id="ssao" min_value="0" max_value="2" width="50%"/>
</div>
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<label text="Shadows (requires restart)" I18N="Video settings"/>
<spacer width="10" height="10"/>
<gauge id="shadows" min_value="0" max_value="2" width="50%"/>
</div>
<spacer proportion="1"/>

View File

@ -40,16 +40,6 @@
<label height="100%" I18N="In the video settings" text="Vertical Sync (requires restart)"/>
</div>
<spacer height="5" width="10"/>
<!-- ************ FBO ************ -->
<div width="75%" height="fit" layout="horizontal-row" >
<spacer width="40" height="2" />
<checkbox id="fbos"/>
<spacer width="20" height="2" />
<label height="100%" I18N="In the video settings" text="Use Frame Buffer Objects (requires restart)"/>
</div>
<spacer height="10" width="10"/>
<!-- ************ RESOLUTION CHOICE ************ -->

39
data/shaders/MLAA_COPYING Normal file
View File

@ -0,0 +1,39 @@
/**
* Copyright (C) 2010 Jorge Jimenez (jorge@iryoku.com)
* Copyright (C) 2010 Belen Masia (bmasia@unizar.es)
* Copyright (C) 2010 Jose I. Echevarria (joseignacioechevarria@gmail.com)
* Copyright (C) 2010 Fernando Navarro (fernandn@microsoft.com)
* Copyright (C) 2010 Diego Gutierrez (diegog@unizar.es)
* Copyright (C) 2011 Lauri Kasanen (cand@gmx.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the following statement:
*
* "Uses Jimenez's MLAA. Copyright (C) 2010 by Jorge Jimenez, Belen Masia,
* Jose I. Echevarria, Fernando Navarro and Diego Gutierrez."
*
* Only for use in the Mesa project, this point 2 is filled by naming the
* technique Jimenez's MLAA in the Mesa config options.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holders.
*/

13
data/shaders/bloom.frag Normal file
View File

@ -0,0 +1,13 @@
uniform sampler2D tex;
uniform float low;
void main()
{
vec3 weights = vec3(0.2126, 0.7152, 0.0722); // ITU-R BT. 709
vec3 col = texture2D(tex, gl_TexCoord[0].xy).xyz;
float luma = dot(weights, col);
col *= smoothstep(low, 0.9, luma);
gl_FragColor = vec4(col, 1.0);
}

View File

@ -0,0 +1,10 @@
uniform sampler2D tex;
void main()
{
vec4 col = texture2D(tex, gl_TexCoord[0].xy);
col.xyz *= 10.0 * col.a;
gl_FragColor = vec4(col.xyz, 1.0);
}

View File

@ -0,0 +1,11 @@
uniform float power;
uniform sampler2D tex;
void main()
{
vec4 col = texture2D(tex, gl_TexCoord[0].xy);
if (col.a < 0.5)
discard;
gl_FragColor = vec4(col.xyz, power);
}

View File

@ -15,13 +15,12 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
uniform sampler2D main_texture;
uniform sampler2D tex;
uniform float transparency;
varying vec2 uv;
void main()
{
gl_FragColor = texture2D(main_texture, uv);
gl_FragColor = texture2D(tex, uv);
gl_FragColor.a *= transparency;
}

View File

@ -0,0 +1,17 @@
uniform sampler2D tex;
uniform sampler2D caustictex;
uniform vec2 dir;
uniform vec2 dir2;
void main()
{
vec2 tc = gl_TexCoord[0].xy;
vec3 col = texture2D(tex, tc).xyz;
float caustic = texture2D(caustictex, tc + dir).x;
float caustic2 = texture2D(caustictex, (tc.yx + dir2 * vec2(-0.6, 0.3)) * vec2(0.6)).x;
col += caustic * caustic2 * 10.0;
gl_FragColor = vec4(col, 1.0);
}

View File

@ -0,0 +1,25 @@
uniform sampler2D tex;
uniform sampler2D oldtex;
uniform vec2 pixel;
uniform vec2 multi;
uniform int size;
void main()
{
float res = 0.0;
vec2 tc = gl_TexCoord[0].xy;
// tc.y = 1.0 - tc.y;
tc *= multi;
for (int i = 0; i < size; i++)
{
float col = texture2D(tex, tc).x;
res = max(col, res);
tc += pixel;
}
float old = texture2D(oldtex, gl_TexCoord[0].xy).x;
gl_FragColor = vec4(mix(old, res, 0.7));
}

View File

@ -0,0 +1,6 @@
uniform vec3 col;
void main()
{
gl_FragColor = vec4(col, 1.0);
}

View File

@ -0,0 +1,11 @@
uniform vec3 col;
uniform sampler2D tex;
void main()
{
float alpha = texture2D(tex, gl_TexCoord[0].xy).a;
if (alpha < 0.5)
discard;
gl_FragColor = vec4(col, 1.0);
}

View File

@ -0,0 +1,40 @@
uniform sampler2D tex;
uniform vec2 screen;
uniform vec2 dir;
uniform vec2 dir2;
varying float camdist;
void main()
{
vec2 tc = gl_TexCoord[0].xy;
vec4 col = vec4(0.0);
const float maxlen = 0.02;
float horiz = texture2D(tex, tc + dir).x;
float vert = texture2D(tex, (tc.yx + dir2) * vec2(0.9)).x;
vec2 offset = vec2(horiz, vert);
offset *= 2.0;
offset -= 1.0;
// Fade according to distance to cam
float fade = 1.0 - smoothstep(1.0, 40.0, camdist);
// Fade according to distance from the edges
vec2 edger = gl_TexCoord[1].xy;
const float mindist = 0.1;
fade *= smoothstep(0.0, mindist, edger.x) * smoothstep(0.0, mindist, edger.y) *
(1.0 - smoothstep(1.0 - mindist, 1.0, edger.x)) *
(1.0 - smoothstep(1.0 - mindist, 1.0, edger.y));
offset *= 50.0 * fade * maxlen;
col.r = step(offset.x, 0.0) * -offset.x;
col.g = step(0.0, offset.x) * offset.x;
col.b = step(offset.y, 0.0) * -offset.y;
col.a = step(0.0, offset.y) * offset.y;
gl_FragColor = col;
}

View File

@ -0,0 +1,9 @@
varying float camdist;
void main() {
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
camdist = length((gl_ModelViewMatrix * gl_Vertex).xyz);
}

View File

@ -0,0 +1,6 @@
void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
gl_Position = (gl_ModelViewProjectionMatrix * gl_Vertex).xyww;
gl_FrontColor = gl_Color;
}

9
data/shaders/flip.frag Normal file
View File

@ -0,0 +1,9 @@
uniform sampler2D tex;
void main()
{
vec2 texc = gl_TexCoord[0].xy;
texc.y = 1.0 - texc.y;
gl_FragColor = texture2D(tex, texc);
}

34
data/shaders/fog.frag Normal file
View File

@ -0,0 +1,34 @@
uniform sampler2D tex;
uniform float fogmax;
uniform float startH;
uniform float endH;
uniform float start;
uniform float end;
uniform vec3 col;
uniform vec3 campos;
uniform mat4 ipvmat;
float decdepth(vec4 rgba) {
return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
}
void main()
{
float z = decdepth(vec4(texture2D(tex, gl_TexCoord[0].xy).xyz, 0.0));
vec3 tmp = vec3(gl_TexCoord[0].xy, z);
tmp = tmp * 2.0 - 1.0;
vec4 xpos = vec4(tmp, 1.0);
xpos = ipvmat * xpos;
xpos.xyz /= xpos.w;
float dist = distance(campos, xpos.xyz);
float fog = smoothstep(start, end, dist);
fog *= 1.0 - smoothstep(startH, endH, xpos.y);
fog = min(fog, fogmax);
gl_FragColor = vec4(col, fog);
}

View File

@ -0,0 +1,19 @@
uniform sampler2D tex;
uniform vec2 pixel;
// Gaussian separated blur with radius 3.
void main()
{
vec4 sum = vec4(0.0);
float X = gl_TexCoord[0].x;
float Y = gl_TexCoord[0].y;
sum += texture2D(tex, vec2(X - 3.0 * pixel.x, Y)) * 0.03125;
sum += texture2D(tex, vec2(X - 1.3333 * pixel.x, Y)) * 0.328125;
sum += texture2D(tex, vec2(X, Y)) * 0.273438;
sum += texture2D(tex, vec2(X + 1.3333 * pixel.x, Y)) * 0.328125;
sum += texture2D(tex, vec2(X + 3.0 * pixel.x, Y)) * 0.03125;
gl_FragColor = sum;
}

View File

@ -0,0 +1,19 @@
uniform sampler2D tex;
uniform vec2 pixel;
// Gaussian separated blur with radius 3.
void main()
{
vec4 sum = vec4(0.0);
float X = gl_TexCoord[0].x;
float Y = gl_TexCoord[0].y;
sum += texture2D(tex, vec2(X, Y - 3.0 * pixel.y)) * 0.03125;
sum += texture2D(tex, vec2(X, Y - 1.3333 * pixel.y)) * 0.328125;
sum += texture2D(tex, vec2(X, Y)) * 0.273438;
sum += texture2D(tex, vec2(X, Y + 1.3333 * pixel.y)) * 0.328125;
sum += texture2D(tex, vec2(X, Y + 3.0 * pixel.y)) * 0.03125;
gl_FragColor = sum;
}

View File

@ -0,0 +1,21 @@
uniform sampler2D tex;
uniform vec2 pixel;
// Gaussian separated blur with radius 6.
void main()
{
vec4 sum = vec4(0.0);
float X = gl_TexCoord[0].x;
float Y = gl_TexCoord[0].y;
sum += texture2D(tex, vec2(X - 5.13333 * pixel.x, Y)) * 0.00640869;
sum += texture2D(tex, vec2(X - 3.26667 * pixel.x, Y)) * 0.083313;
sum += texture2D(tex, vec2(X - 1.4 * pixel.x, Y)) * 0.305481;
sum += texture2D(tex, vec2(X, Y)) * 0.209473;
sum += texture2D(tex, vec2(X + 1.4 * pixel.x, Y)) * 0.305481;
sum += texture2D(tex, vec2(X + 3.26667 * pixel.x, Y)) * 0.083313;
sum += texture2D(tex, vec2(X + 5.13333 * pixel.x, Y)) * 0.00640869;
gl_FragColor = sum;
}

View File

@ -0,0 +1,21 @@
uniform sampler2D tex;
uniform vec2 pixel;
// Gaussian separated blur with radius 6.
void main()
{
vec4 sum = vec4(0.0);
float X = gl_TexCoord[0].x;
float Y = gl_TexCoord[0].y;
sum += texture2D(tex, vec2(X, Y - 5.13333 * pixel.y)) * 0.00640869;
sum += texture2D(tex, vec2(X, Y - 3.26667 * pixel.y)) * 0.083313;
sum += texture2D(tex, vec2(X, Y - 1.4 * pixel.y)) * 0.305481;
sum += texture2D(tex, vec2(X, Y)) * 0.209473;
sum += texture2D(tex, vec2(X, Y + 1.4 * pixel.y)) * 0.305481;
sum += texture2D(tex, vec2(X, Y + 3.26667 * pixel.y)) * 0.083313;
sum += texture2D(tex, vec2(X, Y + 5.13333 * pixel.y)) * 0.00640869;
gl_FragColor = sum;
}

16
data/shaders/glow.frag Normal file
View File

@ -0,0 +1,16 @@
uniform sampler2D tex;
uniform vec2 res;
void main()
{
vec2 coords = gl_FragCoord.xy / res;
vec4 col = texture2D(tex, coords);
float alpha = col.a;
if (alpha < 0.04) discard;
col *= vec4(vec3(4.0), 1.5);
gl_FragColor = col;
}

16
data/shaders/godfade.frag Normal file
View File

@ -0,0 +1,16 @@
uniform sampler2D tex;
uniform vec3 col;
void main()
{
vec4 res = texture2D(tex, gl_TexCoord[0].xy);
// Keep the sun fully bright, but fade the sky
float mul = distance(res.xyz, col);
mul = step(mul, 0.02);
mul *= 0.97;
res = res * vec4(mul);
gl_FragColor = res;
}

29
data/shaders/godray.frag Normal file
View File

@ -0,0 +1,29 @@
uniform sampler2D tex;
uniform vec2 sunpos;
#define SAMPLES 12
const float decaystep = 0.88;
void main()
{
vec2 texc = gl_TexCoord[0].xy;
vec2 tosun = sunpos - texc;
if (dot(tosun, tosun) > 0.49) discard;
vec2 dist = tosun * 1.0/(float(SAMPLES) * 1.12);
vec3 col = texture2D(tex, texc).xyz;
float decay = 1.0;
for (int i = 0; i < SAMPLES; i++) {
texc += dist;
vec3 here = texture2D(tex, texc).xyz;
here *= decay;
col += here;
decay *= decaystep;
}
gl_FragColor = vec4(col, 1.0) * 0.8;
}

View File

@ -1,54 +1,8 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 the SuperTuxKart team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
uniform vec4 fogColor;
uniform float fogFrom;
uniform float fogTo;
uniform int fog;
uniform sampler2D tex;
varying vec4 coord;
void main()
{
vec4 color = texture2D(tex, gl_TexCoord[0].st);
vec4 solidColor = vec4(color.r, color.g, color.b, 1);
if (fog == 1)
{
if (coord.z > fogTo)
{
gl_FragColor = fogColor;
gl_FragColor.a = color.a;
}
else if (coord.z > fogFrom)
{
float fogIntensity = (coord.z - fogFrom) / (fogTo - fogFrom);
vec4 color2 = fogIntensity*fogColor + (1.0 - fogIntensity)*solidColor;
color2.a = color.a;
gl_FragColor = color2;
}
else
{
gl_FragColor = color;
}
}
else
{
gl_FragColor = color;
}
}

View File

@ -1,33 +1,11 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 the SuperTuxKart team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
uniform float angle;
uniform float amplitude;
varying vec4 coord;
uniform vec3 windDir;
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
vec4 vertexPosition = ftransform(); //gl_ModelViewMatrix * gl_Vertex;
vertexPosition += vec4(1,0,0,0) * amplitude * gl_Color.r * sin(angle);
gl_Position = vertexPosition;
gl_FrontColor = vec4(1,1,1,1);
gl_BackColor = vec4(1,1,1,1);
coord = vertexPosition;
vec4 vertexPosition = gl_Vertex;
vertexPosition.xyz += windDir * gl_Color.r;
gl_Position = gl_ModelViewProjectionMatrix * vertexPosition;
}

View File

@ -0,0 +1,19 @@
uniform sampler2D tex;
uniform vec3 ambient;
uniform sampler2D spectex;
void main()
{
vec2 texc = gl_TexCoord[0].xy;
vec4 col = texture2D(tex, texc);
vec4 specular = texture2D(spectex, texc);
col.xyz += ambient;
float spec = col.a - 0.05;
spec *= specular.a;
col.xyz += spec;
col.a = 1.0;
gl_FragColor = col;
}

52
data/shaders/mipviz.frag Normal file
View File

@ -0,0 +1,52 @@
#version 120
uniform sampler2D tex;
uniform vec2 texsize;
uniform int notex;
float miplevel(in vec2 texture_coordinate)
{
// The OpenGL Graphics System: A Specification 4.2
// - chapter 3.9.11, equation 3.21
vec2 dx_vtc = dFdx(texture_coordinate);
vec2 dy_vtc = dFdy(texture_coordinate);
float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
return 0.5 * log2(delta_max_sqr); // == log2(sqrt(delta_max_sqr));
}
void main() {
if (notex != 0) {
gl_FragColor = gl_Color;
return;
}
// Buggy Intel windows driver workaround
vec4 levels[6] = vec4[](
vec4(0.0, 0.0, 1.0, 0.8),
vec4(0.0, 0.5, 1.0, 0.4),
vec4(1.0, 1.0, 1.0, 0.0),
vec4(1.0, 0.7, 0.0, 0.2),
vec4(1.0, 0.3, 0.0, 0.6),
vec4(1.0, 0.0, 0.0, 0.8)
);
float mip = miplevel(texsize * gl_TexCoord[0].xy) + 2.0;
mip = clamp(mip, 0.0, 5.0);
int lowmip = int(mip);
int highmip = lowmip + 1;
if (highmip > 5)
highmip = 5;
float mixer = fract(mip);
vec4 mixcol = mix(levels[lowmip], levels[highmip], mixer);
vec4 tcol = texture2D(tex, gl_TexCoord[0].xy);
vec3 col = mix(tcol.xyz, mixcol.xyz, mixcol.a);
gl_FragColor = vec4(col, tcol.a);
}

View File

@ -0,0 +1,112 @@
#define MAX_SEARCH_STEPS 8.0
#define MAX_DISTANCE 33.0
#extension GL_ARB_shader_texture_lod: enable
uniform sampler2D edgesMap;
uniform sampler2D areaMap;
uniform vec2 PIXEL_SIZE;
/**
* This one just returns the first level of a mip map chain, which allow us to
* avoid the nasty ddx/ddy warnings, even improving the performance a little
* bit.
*/
vec4 tex2Doffset(sampler2D map, vec2 texcoord, vec2 offset) {
return texture2DLod(map, texcoord + PIXEL_SIZE * offset, 0.0);
}
float SearchXLeft(vec2 texcoord) {
// We compare with 0.9 to prevent bilinear access precision problems.
float i;
float e = 0.0;
for (i = -1.5; i > -2.0 * MAX_SEARCH_STEPS; i -= 2.0) {
e = tex2Doffset(edgesMap, texcoord, vec2(i, 0.0)).g;
if (e < 0.9) break;
}
return max(i + 1.5 - 2.0 * e, -2.0 * MAX_SEARCH_STEPS);
}
float SearchXRight(vec2 texcoord) {
float i;
float e = 0.0;
for (i = 1.5; i < 2.0 * MAX_SEARCH_STEPS; i += 2.0) {
e = tex2Doffset(edgesMap, texcoord, vec2(i, 0.0)).g;
if (e < 0.9) break;
}
return min(i - 1.5 + 2.0 * e, 2.0 * MAX_SEARCH_STEPS);
}
float SearchYDown(vec2 texcoord) {
float i;
float e = 0.0;
for (i = -1.5; i > -2.0 * MAX_SEARCH_STEPS; i -= 2.0) {
e = tex2Doffset(edgesMap, texcoord, vec2(i, 0.0).yx).r;
if (e < 0.9) break;
}
return max(i + 1.5 - 2.0 * e, -2.0 * MAX_SEARCH_STEPS);
}
float SearchYUp(vec2 texcoord) {
float i;
float e = 0.0;
for (i = 1.5; i < 2.0 * MAX_SEARCH_STEPS; i += 2.0) {
e = tex2Doffset(edgesMap, texcoord, vec2(i, 0.0).yx).r;
if (e < 0.9) break;
}
return min(i - 1.5 + 2.0 * e, 2.0 * MAX_SEARCH_STEPS);
}
vec2 round(vec2 invec) {
return vec2(floor(abs(invec) + vec2(0.5)) * sign(invec));
}
vec2 Area(vec2 distance, float e1, float e2) {
// * By dividing by areaSize - 1.0 below we are implicitely offsetting to
// always fall inside of a pixel
// * Rounding prevents bilinear access precision problems
float areaSize = MAX_DISTANCE * 5.0;
vec2 pixcoord = MAX_DISTANCE * round(4.0 * vec2(e1, e2)) + distance;
vec2 texcoord = pixcoord / (areaSize - 1.0);
return texture2DLod(areaMap, texcoord, 0.0).ra;
}
void main() {
vec4 areas = vec4(0.0);
vec2 e = texture2D(edgesMap, gl_TexCoord[0].xy).rg;
if (e.g != 0.0) { // Edge at north
// Search distances to the left and to the right:
vec2 d = vec2(SearchXLeft(gl_TexCoord[0].xy), SearchXRight(gl_TexCoord[0].xy));
// Now fetch the crossing edges. Instead of sampling between edgels, we
// sample at 0.25, to be able to discern what value has each edgel:
vec4 coords = vec4(d.x, 0.25, d.y + 1.0, 0.25) * PIXEL_SIZE.xyxy + gl_TexCoord[0].xyxy;
float e1 = texture2DLod(edgesMap, coords.xy, 0.0).r;
float e2 = texture2DLod(edgesMap, coords.zw, 0.0).r;
// Ok, we know how this pattern looks like, now it is time for getting
// the actual area:
areas.rg = Area(abs(d), e1, e2);
}
if (e.r != 0.0) { // Edge at west
// Search distances to the top and to the bottom:
vec2 d = vec2(SearchYUp(gl_TexCoord[0].xy), SearchYDown(gl_TexCoord[0].xy));
// Now fetch the crossing edges (yet again):
vec4 coords = vec4(-0.25, d.x, -0.25, d.y - 1.0) * PIXEL_SIZE.xyxy + gl_TexCoord[0].xyxy;
float e1 = texture2DLod(edgesMap, coords.xy, 0.0).g;
float e2 = texture2DLod(edgesMap, coords.zw, 0.0).g;
// Get the area for this direction:
areas.ba = Area(abs(d), e1, e2);
}
gl_FragColor = areas;
}

View File

@ -0,0 +1,25 @@
varying vec4 offset[2];
uniform sampler2D colorMapG;
const float threshold = 0.1f;
void main() {
vec3 weights = vec3(0.2126,0.7152, 0.0722); // ITU-R BT. 709
/**
* Luma calculation requires gamma-corrected colors:
*/
float L = dot(texture2D(colorMapG, gl_TexCoord[0].xy).rgb, weights);
float Lleft = dot(texture2D(colorMapG, offset[0].xy).rgb, weights);
float Ltop = dot(texture2D(colorMapG, offset[0].zw).rgb, weights);
float Lright = dot(texture2D(colorMapG, offset[1].xy).rgb, weights);
float Lbottom = dot(texture2D(colorMapG, offset[1].zw).rgb, weights);
vec4 delta = abs(vec4(L) - vec4(Lleft, Ltop, Lright, Lbottom));
vec4 edges = step(vec4(threshold), delta);
if (dot(edges, vec4(1.0)) == 0.0)
discard;
gl_FragColor = edges;
}

View File

@ -0,0 +1,38 @@
varying vec4 offset[2];
uniform sampler2D blendMap;
uniform sampler2D colorMap;
void main() {
// Fetch the blending weights for current pixel:
vec4 topLeft = texture2D(blendMap, gl_TexCoord[0].xy);
float bottom = texture2D(blendMap, offset[1].zw).g;
float right = texture2D(blendMap, offset[1].xy).a;
vec4 a = vec4(topLeft.r, bottom, topLeft.b, right);
// Up to 4 lines can be crossing a pixel (one in each edge). So, we perform
// a weighted average, where the weight of each line is 'a' cubed, which
// favors blending and works well in practice.
vec4 w = a * a * a;
// There is some blending weight with a value greater than 0.0?
float sum = dot(w, vec4(1.0));
if (sum < 1e-5)
discard;
vec4 color = vec4(0.0);
// Add the contributions of the possible 4 lines that can cross this pixel:
vec4 C = texture2D(colorMap, gl_TexCoord[0].xy);
vec4 Cleft = texture2D(colorMap, offset[0].xy);
vec4 Ctop = texture2D(colorMap, offset[0].zw);
vec4 Cright = texture2D(colorMap, offset[1].xy);
vec4 Cbottom = texture2D(colorMap, offset[1].zw);
color = mix(C, Ctop, a.r) * w.r + color;
color = mix(C, Cbottom, a.g) * w.g + color;
color = mix(C, Cleft, a.b) * w.b + color;
color = mix(C, Cright, a.a) * w.a + color;
// Normalize the resulting color and we are finished!
gl_FragColor = color / sum;
}

View File

@ -0,0 +1,12 @@
varying vec4 offset[2];
uniform vec2 PIXEL_SIZE;
void main() {
gl_Position = ftransform();
vec4 invy = gl_MultiTexCoord0;
// invy.y = 1.0 - invy.y;
gl_TexCoord[0] = invy;
offset[0] = invy.xyxy + PIXEL_SIZE.xyxy * vec4(-1.0, 0.0, 0.0, 1.0);
offset[1] = invy.xyxy + PIXEL_SIZE.xyxy * vec4( 1.0, 0.0, 0.0, -1.0);
}

View File

@ -41,7 +41,7 @@ uniform float mask_radius;
uniform float max_tex_height;
// Number of samples used for blurring
#define NB_SAMPLES 12
#define NB_SAMPLES 8
void main()
{
@ -50,14 +50,6 @@ void main()
// Sample the color buffer
vec3 color = texture2D(color_buffer, texcoords).rgb;
// If no motion blur is needed, don't do any of the blur computation,
// just return the color from the texture.
if(boost_amount==0.0)
{
gl_FragColor = vec4(color, 1.0);
return;
}
// Compute the blur direction.
// IMPORTANT: we don't normalize it so that it avoids a glitch around 'center',
// plus it naturally scales the motion blur in a cool way :)

View File

@ -0,0 +1,10 @@
uniform sampler2D tex1;
uniform sampler2D tex2;
void main()
{
vec4 col1 = texture2D(tex1, gl_TexCoord[0].xy);
vec4 col2 = vec4(vec3(texture2D(tex2, gl_TexCoord[0].xy).x), 1.0);
gl_FragColor = col1 * col2;
}

View File

@ -4,7 +4,7 @@
uniform sampler2D BumpTex; //The bump-map
uniform sampler2D DecalTex; //The texture
uniform sampler2D LightMapTex;
int HasLightMap;
uniform int HasLightMap;
// New bumpmapping
varying vec3 lightVec;
@ -19,7 +19,7 @@ void main()
normal = normalize (normal);
// compute diffuse lighting
float lamberFactor = max (dot (lightVec, normal), 0.0) ;
float lamberFactor = max (dot (lightVec, normal), 0.0);
vec4 diffuseMaterial;
diffuseMaterial = texture2D (DecalTex, gl_TexCoord[0].st);

View File

@ -0,0 +1,40 @@
varying vec3 nor;
uniform sampler2D tex;
uniform sampler2D lighttex;
uniform float far;
uniform int hastex;
uniform int haslightmap;
uniform float objectid;
const float near = 1.0;
vec4 encdepth(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
}
void main() {
float linear_z = (2.0 * near) / (far + near - gl_FragCoord.z * (far - near));
// Tune for better inside range without losing outdoors
linear_z *= 2.0;
vec4 light = vec4(1.0);
if (haslightmap != 0) {
light = texture2D(lighttex, gl_TexCoord[1].xy);
}
if (hastex != 0)
gl_FragData[0] = texture2D(tex, gl_TexCoord[0].xy) * light;
else
gl_FragData[0] = gl_Color;
gl_FragData[1] = vec4(nor, linear_z);
gl_FragData[2] = vec4(encdepth(gl_FragCoord.z).xyz, objectid);
}

View File

@ -0,0 +1,14 @@
varying vec3 nor;
uniform mat4 invtworldm;
void main() {
nor = (invtworldm * vec4(gl_Normal, 0.0)).xyz;
nor = normalize(nor);
nor = nor * 0.5 + 0.5;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}

View File

@ -0,0 +1,37 @@
varying vec3 nor;
uniform sampler2D tex;
uniform float far;
uniform int hastex;
uniform float objectid;
const float near = 1.0;
vec4 encdepth(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
}
void main() {
float linear_z = (2.0 * near) / (far + near - gl_FragCoord.z * (far - near));
// Tune for better inside range without losing outdoors
linear_z *= 2.0;
if (hastex != 0) {
vec4 col = texture2D(tex, gl_TexCoord[0].xy);
if (col.a < 0.5)
discard;
gl_FragData[0] = col;
} else {
gl_FragData[0] = gl_Color;
}
gl_FragData[1] = vec4(nor, linear_z);
gl_FragData[2] = vec4(encdepth(gl_FragCoord.z).xyz, objectid);
}

View File

@ -0,0 +1,45 @@
varying vec3 nor;
uniform sampler2D tex;
uniform float far;
uniform int hastex;
uniform float objectid;
varying vec3 eyenor;
varying vec3 viewpos;
const float near = 1.0;
vec4 encdepth(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
}
void main() {
float linear_z = (2.0 * near) / (far + near - gl_FragCoord.z * (far - near));
// Tune for better inside range without losing outdoors
linear_z *= 2.0;
float rim = 1.0 - dot(eyenor, viewpos);
rim = smoothstep(0.5, 1.5, rim) * 0.35;
if (hastex != 0) {
vec4 col = texture2D(tex, gl_TexCoord[0].xy);
if (col.a < 0.5)
discard;
col.xyz += rim;
gl_FragData[0] = col;
} else {
gl_FragData[0] = gl_Color + vec4(vec3(rim), 0.0);
}
gl_FragData[1] = vec4(nor, linear_z);
gl_FragData[2] = vec4(encdepth(gl_FragCoord.z).xyz, objectid);
}

View File

@ -0,0 +1,19 @@
varying vec3 nor;
uniform mat4 invtworldm;
varying vec3 eyenor;
varying vec3 viewpos;
void main() {
nor = (invtworldm * vec4(gl_Normal, 0.0)).xyz;
nor = normalize(nor);
nor = nor * 0.5 + 0.5;
eyenor = gl_NormalMatrix * gl_Normal;
viewpos = -normalize((gl_ModelViewMatrix * gl_Vertex).xyz);
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}

View File

@ -0,0 +1,42 @@
varying vec3 nor;
uniform sampler2D tex;
uniform float far;
uniform float objectid;
varying vec3 eyenor;
varying vec3 viewpos;
const float near = 1.0;
vec4 encdepth(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
}
void main() {
float linear_z = (2.0 * near) / (far + near - gl_FragCoord.z * (far - near));
// Tune for better inside range without losing outdoors
linear_z *= 2.0;
// Calculate the spherical UV
const vec3 forward = vec3(0.0, 0.0, 1.0);
// get the angle between the forward vector and the horizontal portion of the normal
vec3 normal_x = normalize(vec3(eyenor.x, 0.0, eyenor.z));
float sin_theta_x = length(cross( forward, normal_x )) * eyenor.x/abs(eyenor.x);
// get the angle between the forward vector and the vertical portion of the normal
vec3 normal_y = normalize(vec3(0.0, eyenor.y, eyenor.z));
float sin_theta_y = length(cross( forward, normal_y )) * eyenor.y/abs(eyenor.y);
vec4 detail0 = texture2D(tex, vec2(0.5 + sin_theta_x*0.5, 0.5 + sin_theta_y*0.5));
gl_FragData[0] = detail0 * gl_Color;
gl_FragData[1] = vec4(nor, linear_z);
gl_FragData[2] = vec4(encdepth(gl_FragCoord.z).xyz, objectid);
}

6
data/shaders/pass.frag Normal file
View File

@ -0,0 +1,6 @@
uniform sampler2D tex;
void main()
{
gl_FragColor = texture2D(tex, gl_TexCoord[0].xy);
}

6
data/shaders/pass.vert Normal file
View File

@ -0,0 +1,6 @@
void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}

View File

@ -0,0 +1,52 @@
uniform sampler2D tex;
uniform vec2 pixel;
// Separated penumbra, horizontal
void main()
{
float sum = 0.0;
vec4 tmp;
float X = gl_TexCoord[0].x;
float Y = gl_TexCoord[0].y;
float width = 0.0;
float zsum = 0.00001;
tmp = texture2D(tex, vec2(X - 5.13333 * pixel.x, Y));
sum += tmp.x * 0.00640869;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X - 3.26667 * pixel.x, Y));
sum += tmp.x * 0.083313;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X - 1.4 * pixel.x, Y));
sum += tmp.x * 0.305481;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X, Y));
sum += tmp.x * 0.209473;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X + 1.4 * pixel.x, Y));
sum += tmp.x * 0.305481;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X + 3.26667 * pixel.x, Y));
sum += tmp.x * 0.083313;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X + 5.13333 * pixel.x, Y));
sum += tmp.x * 0.00640869;
zsum += tmp.z;
width += tmp.y;
float hasz = step(0.7, zsum);
gl_FragColor = vec4(sum, (width / zsum) * hasz, hasz, 1.0);
}

View File

@ -0,0 +1,52 @@
uniform sampler2D tex;
uniform vec2 pixel;
// Separated penumbra, vertical
void main()
{
float sum = 0.0;
vec4 tmp;
float X = gl_TexCoord[0].x;
float Y = gl_TexCoord[0].y;
float width = 0.0;
float zsum = 0.00001;
tmp = texture2D(tex, vec2(X, Y - 5.13333 * pixel.y));
sum += tmp.x * 0.00640869;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X, Y - 3.26667 * pixel.y));
sum += tmp.x * 0.083313;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X, Y - 1.4 * pixel.y));
sum += tmp.x * 0.305481;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X, Y));
sum += tmp.x * 0.209473;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X, Y + 1.4 * pixel.y));
sum += tmp.x * 0.305481;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X, Y + 3.26667 * pixel.y));
sum += tmp.x * 0.083313;
zsum += tmp.z;
width += tmp.y;
tmp = texture2D(tex, vec2(X, Y + 5.13333 * pixel.y));
sum += tmp.x * 0.00640869;
zsum += tmp.z;
width += tmp.y;
float hasz = step(0.7, zsum);
gl_FragColor = vec4(sum, (width / zsum) * hasz, hasz, 1.0);
}

View File

@ -0,0 +1,50 @@
uniform sampler2D ntex;
uniform sampler2D dtex;
uniform vec3 center;
uniform vec3 col;
uniform vec3 campos;
uniform float r;
uniform float spec;
uniform vec2 screen;
uniform mat4 invprojview;
float decdepth(vec4 rgba) {
return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
}
void main() {
vec2 texc = gl_FragCoord.xy / screen;
float z = decdepth(vec4(texture2D(dtex, texc).xyz, 0.0));
if (z < 0.03) discard;
vec3 tmp = vec3(texc, z);
tmp = tmp * 2.0 - 1.0;
vec4 xpos = vec4(tmp, 1.0);
xpos = invprojview * xpos;
xpos.xyz /= xpos.w;
float d = distance(center, xpos.xyz);
if (d > r) discard;
float att = 1.0 - smoothstep(0.0, r, d);
vec3 norm = texture2D(ntex, texc).xyz;
norm = (norm - 0.5) * 2.0;
vec3 camdir = normalize(campos - xpos.xyz);
vec3 L = normalize(center - xpos.xyz);
vec3 H = normalize(L + camdir);
float NdotL = max(0.0, dot(norm, L)) * att;
if (NdotL < 0.01) discard;
float NdotH = max(0.0, dot(norm, H));
NdotH = pow(NdotH, spec);
NdotH += 0.05; // offset so that the alpha test doesn't kill us
gl_FragColor = NdotL * vec4(col, NdotH);
}

View File

@ -0,0 +1,26 @@
uniform sampler2D tex;
uniform sampler2D dtex;
uniform int viz;
void main()
{
vec2 tc = gl_TexCoord[0].xy;
vec4 shiftval = texture2D(dtex, tc) / vec4(50.0);
vec2 shift;
shift.x = -shiftval.x + shiftval.y;
shift.y = -shiftval.z + shiftval.w;
tc += shift;
vec4 newcol = texture2D(tex, tc);
if (viz < 1)
{
gl_FragColor = newcol;
} else
{
gl_FragColor = shiftval * vec4(50.0);
}
}

6
data/shaders/rain.frag Normal file
View File

@ -0,0 +1,6 @@
uniform sampler2D tex;
void main()
{
gl_FragColor = texture2D(tex, gl_TexCoord[0].xy);
}

33
data/shaders/rain.vert Normal file
View File

@ -0,0 +1,33 @@
uniform float screenw;
uniform float time;
uniform mat4 viewm;
uniform vec3 campos;
void main()
{
const float size = 0.5;
// This simulation will run accurately for a bit under five days.
vec4 start = gl_Vertex;
start.y -= time;
// How many times has it fell?
float count = floor(start.y / 24.0);
start.x += sin(count);
start.z += cos(count);
vec2 signs = sign(start.xz);
start.xz = mod(start.xz, 17.5) * signs;
start.y = mod(start.y, 24.0) - 3.0;
start.xyz += campos;
vec4 eyepos = viewm * start;
vec4 projCorner = gl_ProjectionMatrix * vec4(vec2(size), eyepos.z, eyepos.w);
gl_PointSize = screenw * projCorner.x / projCorner.w;
gl_Position = gl_ProjectionMatrix * eyepos;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@ -0,0 +1,44 @@
uniform sampler2D halft; // half is a reserved word
uniform sampler2D quarter;
uniform sampler2D eighth;
void main()
{
vec3 val[3];
val[0] = texture2D(halft, gl_TexCoord[0].xy).xyz;
val[1] = texture2D(quarter, gl_TexCoord[0].xy).xyz;
val[2] = texture2D(eighth, gl_TexCoord[0].xy).xyz;
// Find the first level with a penumbra value
int i;
float q = 0.0;
float outval = 1.0;
float hasshadow = dot(vec3(1.0), vec3(val[0].z, val[1].z, val[2].z));
if (hasshadow > 0.9)
{
for (i = 0; i < 3; i++)
{
if (val[i].z > 0.9)
{
q = val[i].y;
break;
}
}
q *= 8.0;
q = max(1.0, q);
q = log2(q);
q = min(1.9, q);
// q is now between 0 and 1.9.
int down = int(floor(q));
int up = down + 1;
float interp = q - float(down);
outval = 1.0 - mix(val[down].x, val[up].x, interp);
}
gl_FragColor = vec4(vec3(outval), 1.0);
}

View File

@ -0,0 +1,70 @@
uniform sampler2D ntex;
uniform sampler2D ctex;
uniform vec3 campos;
uniform int low;
varying vec3 wpos;
varying vec2 texc;
float luminanceImp()
{
// A full-res fetch kills on low-end
if (low > 0) return 1.0;
const vec3 weights = vec3(0.2126, 0.7152, 0.0722); // ITU-R BT. 709
vec3 col = texture2D(ctex, texc).xyz;
float luma = dot(weights, col);
// Dark surfaces need less resolution
float f = smoothstep(0.1, 0.4, luma);
f = max(0.05, f);
return f;
}
float normalImp(vec3 normal)
{
vec3 camdir = normalize(campos - wpos);
vec3 N = normalize(normal);
// Boost surfaces facing the viewer directly
float f = 2.0 * max(0.0, dot(N, camdir));
return f;
}
float depthImp(float linearz)
{
/* const float skip = 0.7;
float f = min(linearz, skip);
f *= 1.0/skip;*/
float z = log(1.0 + linearz * 9.0) / log(10.0);
float f = 1.0 - (z * 0.9);
return f;
}
void main()
{
vec4 ntmp = texture2D(ntex, texc);
vec3 normal = ntmp.xyz * 2.0 - 1.0;
float linearz = ntmp.a;
float importance = normalImp(normal) * depthImp(linearz) * luminanceImp();
importance = clamp(importance, 0.0, 1.0);
float low = step(0.001, importance);
// Quantize it
const float steps = 16.0;
importance *= steps;
importance = ceil(importance) * low;
importance /= steps;
gl_FragColor = vec4(importance);
gl_FragDepth = 1.0 - importance;
}

View File

@ -0,0 +1,30 @@
uniform sampler2D dtex;
uniform mat4 ipvmat;
uniform mat4 shadowmat;
varying vec3 wpos;
varying vec2 texc;
float decdepth(vec4 rgba) {
return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
}
void main()
{
texc = gl_Vertex.xy / vec2(32767.0);
float z = decdepth(vec4(texture2D(dtex, texc).xyz, 0.0));
vec3 tmp = vec3(texc, z);
tmp = tmp * 2.0 - 1.0;
vec4 xpos = vec4(tmp, 1.0);
xpos = ipvmat * xpos;
xpos.xyz /= xpos.w;
wpos = xpos.xyz;
// Now we have this pixel's world-space position. Convert to shadow space.
vec4 pos = shadowmat * vec4(xpos.xyz, 1.0);
gl_Position = pos;
}

View File

@ -0,0 +1,34 @@
uniform sampler2D tex;
uniform int hastex;
uniform int viz;
uniform int wireframe;
uniform float objectid;
vec4 encdepth(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
}
void main() {
if (hastex != 0) {
float alpha = texture2D(tex, gl_TexCoord[0].xy).a;
if (alpha < 0.5)
discard;
}
if (viz < 1)
{
gl_FragColor = vec4(encdepth(gl_FragCoord.z).xyz, objectid);
}
else {
if (wireframe > 0)
gl_FragColor = vec4(1.0);
else
gl_FragColor = texture2D(tex, gl_TexCoord[0].xy);
}
}

View File

@ -0,0 +1,25 @@
uniform sampler2D warpx;
uniform sampler2D warpy;
float decdepth(vec4 rgba) {
return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
}
void main()
{
vec4 pos = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
vec2 tc = pos.xy * vec2(0.5) + vec2(0.5);
float movex = decdepth(texture2D(warpx, tc));
float movey = decdepth(texture2D(warpy, tc));
float dx = movex * 2.0 - 1.0;
float dy = movey * 2.0 - 1.0;
dx *= 2.0;
dy *= 2.0;
gl_Position = pos + vec4(dx, dy, vec2(0.0));
}

View File

@ -0,0 +1,54 @@
uniform sampler2D tex;
uniform int size;
uniform vec2 pixel;
vec4 encdepth(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
}
void main()
{
vec2 origtc = gl_TexCoord[0].xy;
// Get total sum
float first = 1.0, last = 0.0;
float lower = 0.0;
float total = 0.0;
vec2 tc = 0.5 * pixel;
for (int i = 0; i < size; i++)
{
float col = texture2D(tex, tc).x;
lower += col * step(tc.x, origtc.x);
total += col;
if (col > 0.0001)
{
first = min(first, tc.x);
last = max(last, tc.x);
}
tc += pixel;
}
float res = (lower / total) - origtc.x;
// Outside the edges?
if (origtc.x <= first)
{
res = origtc.x * -2.1;
}
else if (origtc.x >= last)
{
res = (1.0 - origtc.x) * 2.1;
}
res = res * 0.5 + 0.5;
res = clamp(res, 0.01, 0.99);
gl_FragColor = encdepth(res);
}

View File

@ -0,0 +1,54 @@
uniform sampler2D tex;
uniform int size;
uniform vec2 pixel;
vec4 encdepth(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
}
void main()
{
vec2 origtc = gl_TexCoord[0].xy;
// Get total sum
float first = 1.0, last = 0.0;
float lower = 0.0;
float total = 0.0;
vec2 tc = pixel * 0.5;
for (int i = 0; i < size; i++)
{
float col = texture2D(tex, tc).x;
lower += col * step(tc.y, origtc.y);
total += col;
if (col > 0.0001)
{
first = min(first, tc.y);
last = max(last, tc.y);
}
tc += pixel;
}
float res = (lower / total) - origtc.y;
// Outside the edges?
if (origtc.y <= first)
{
res = origtc.y * -2.1;
}
else if (origtc.y >= last)
{
res = (1.0 - origtc.y) * 2.1;
}
res = res * 0.5 + 0.5;
res = clamp(res, 0.01, 0.99);
gl_FragColor = encdepth(res);
}

18
data/shaders/snow.frag Normal file
View File

@ -0,0 +1,18 @@
uniform sampler2D tex;
uniform float time;
void main()
{
vec2 change;
change.x = abs(sin(time * gl_Color.r));
change.y = abs(cos(time * gl_Color.g));
change = smoothstep(0.0, 1.0, change) * 0.5;
vec2 tc = gl_TexCoord[0].xy;
tc = smoothstep(0.5 - change, 0.5 + change, tc);
vec4 tcol = texture2D(tex, tc);
gl_FragColor = tcol;
}

7
data/shaders/snow.vert Normal file
View File

@ -0,0 +1,7 @@
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}

View File

@ -1,44 +1,48 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 the SuperTuxKart team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
varying vec3 nor;
uniform float far;
uniform float objectid;
uniform sampler2D tex_layout;
uniform sampler2D tex_detail0;
uniform sampler2D tex_detail1;
uniform sampler2D tex_detail2;
uniform sampler2D tex_detail3;
uniform sampler2D tex_detail4;
varying vec3 normal;
varying vec3 lightdir2;
varying vec4 vertex_color;
//uniform sampler2D tex_detail4;
void main()
{
const float near = 1.0;
vec4 encdepth(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
}
void main() {
float linear_z = (2.0 * near) / (far + near - gl_FragCoord.z * (far - near));
// Tune for better inside range without losing outdoors
linear_z *= 2.0;
// Splatting part
vec4 splatting = texture2D(tex_layout, gl_TexCoord[1].st);
vec4 detail0 = texture2D(tex_detail0, gl_TexCoord[0].st);
vec4 detail1 = texture2D(tex_detail1, gl_TexCoord[0].st);
vec4 detail2 = texture2D(tex_detail2, gl_TexCoord[0].st);
vec4 detail3 = texture2D(tex_detail3, gl_TexCoord[0].st);
vec4 detail4 = texture2D(tex_detail4, gl_TexCoord[0].st);
// vec4 detail4 = texture2D(tex_detail4, gl_TexCoord[0].st);
vec4 detail4 = vec4(0.0);
gl_FragColor = (splatting.r * detail0 +
vec4 splatted = (splatting.r * detail0 +
splatting.g * detail1 +
splatting.b * detail2 +
(1.0 - splatting.r - splatting.g - splatting.b) * detail3 +
(1.0 - splatting.a) * detail4)
* min(1.0, 0.2 + dot(lightdir2, normal)) * vertex_color; // 0.2 is the ambient light.
* gl_Color;
gl_FragData[0] = splatted;
gl_FragData[1] = vec4(nor, linear_z);
gl_FragData[2] = vec4(encdepth(gl_FragCoord.z).xyz, objectid);
}

78
data/shaders/ssao.frag Normal file
View File

@ -0,0 +1,78 @@
#version 120
uniform sampler2D tex;
uniform sampler2D oldtex;
const float totStrength = 2.38;
const float strength = 0.07;
const float falloff = 0.000002;
#define SAMPLES 16
const float invSamples = 1.0 / SAMPLES;
void main(void)
{
// A set of Random(tm) vec2's. 8 1s, 6 0.7s, 2 0.4
// Again not using const because of broken Intel Windows drivers
vec2 vecs[16] = vec2[](vec2(0.43589, -0.9), vec2(-0.9, 0.43589),
vec2(-0.8, -0.6), vec2(0.6, 0.8),
vec2(0.866025, -0.5), vec2(-0.5, 0.866025),
vec2(-0.3, -0.953939), vec2(0.953939, 0.3),
vec2(0.3, -0.781025), vec2(-0.781025, 0.3),
vec2(-0.56, -0.621611), vec2(0.621611, 0.56),
vec2(0.734847, -0.4), vec2(-0.4, 0.734847),
vec2(-0.2, -0.6), vec2(0.6, 0.2));
vec2 uv = gl_TexCoord[0].xy;
vec4 cur = texture2D(tex, uv);
float curdepth = cur.a;
// Will we skip this pixel? (if it's the sky)
float len = dot(vec3(1.0), abs(cur.xyz));
if (len < 0.2 || curdepth > 0.8) discard;
float mytotstrength = 3.0 * totStrength * curdepth * (1.0 - curdepth);
// get the normal of current fragment
vec3 norm = normalize(cur.xyz * vec3(2.0) - vec3(1.0));
float bl = 0.0;
// adjust for the depth, 0.1 close, 0.01 far
float radD = 0.10 - 0.09 * smoothstep(0.0, 0.2, curdepth);
for(int i = 0; i < SAMPLES; ++i) {
vec2 ray = uv + radD * vecs[i];
// get the depth of the occluder fragment
vec4 occluderFragment = texture2D(tex, ray);
float normAcceptable = step(0.2, dot(vec3(1.0), abs(occluderFragment.xyz)));
// get the normal of the occluder fragment
vec3 occNorm = normalize(occluderFragment.xyz * vec3(2.0) - vec3(1.0));
// if depthDifference is negative = occluder is behind current fragment
float depthDifference = curdepth - occluderFragment.a;
// calculate the difference between the normals as a weight
float normDiff = 1.0 - max(dot(occNorm, norm), 0.0);
normDiff = smoothstep(0.1, 0.3, normDiff);
// the falloff equation, starts at falloff and is kind of 1/x^2 falling
bl += step(falloff, depthDifference) * normDiff * normAcceptable *
(1.0 - smoothstep(falloff, strength, depthDifference));
}
// output the result
float ao = 1.0 - mytotstrength * bl * invSamples;
// Mix with old result to avoid flicker
float oldao = texture2D(oldtex, uv).x;
ao = mix(ao, oldao, 0.3);
gl_FragColor = vec4(vec3(ao), curdepth);
}

View File

@ -0,0 +1,58 @@
uniform sampler2D ntex;
uniform sampler2D dtex;
uniform sampler2D cloudtex;
uniform vec3 center;
uniform vec3 col;
uniform vec2 screen;
uniform mat4 invprojview;
uniform int hasclouds;
uniform vec2 wind;
float decdepth(vec4 rgba) {
return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
}
void main() {
vec2 texc = gl_FragCoord.xy / screen;
float z = decdepth(vec4(texture2D(dtex, texc).xyz, 0.0));
if (z < 0.03)
{
// Skyboxes are fully lit
gl_FragData[0] = vec4(1.0);
gl_FragData[1] = vec4(1.0);
return;
}
vec3 norm = texture2D(ntex, texc).xyz;
norm = (norm - 0.5) * 2.0;
// Normalized on the cpu
vec3 L = center;
float NdotL = max(0.0, dot(norm, L));
if (NdotL < 0.01) discard;
vec3 outcol = NdotL * col;
if (hasclouds == 1)
{
vec3 tmp = vec3(texc, z);
tmp = tmp * 2.0 - 1.0;
vec4 xpos = vec4(tmp, 1.0);
xpos = invprojview * xpos;
xpos.xyz /= xpos.w;
vec2 cloudcoord = (xpos.xz * 0.00833333) + wind;
float cloud = texture2D(cloudtex, cloudcoord).x;
//float cloud = step(0.5, cloudcoord.x) * step(0.5, cloudcoord.y);
outcol *= cloud;
}
gl_FragData[0] = vec4(outcol, 0.05);
gl_FragData[1] = vec4(1.0);
}

View File

@ -0,0 +1,106 @@
uniform sampler2D ntex;
uniform sampler2D dtex;
uniform sampler2D cloudtex;
uniform sampler2D shadowtex;
uniform sampler2D warpx;
uniform sampler2D warpy;
uniform vec3 center;
uniform vec3 col;
uniform vec2 screen;
uniform mat4 invprojview;
uniform mat4 shadowmat;
uniform int hasclouds;
uniform vec2 wind;
uniform float shadowoffset;
float decdepth(vec4 rgba) {
return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
}
void main() {
vec2 texc = gl_FragCoord.xy / screen;
vec4 depthread = texture2D(dtex, texc);
float z = decdepth(vec4(depthread.xyz, 0.0));
if (z < 0.03)
{
// Skyboxes are fully lit
gl_FragData[0] = vec4(1.0);
gl_FragData[1] = vec4(0.0);
return;
}
vec3 norm = texture2D(ntex, texc).xyz;
norm = (norm - 0.5) * 2.0;
// Normalized on the cpu
vec3 L = center;
float NdotL = max(0.0, dot(norm, L));
if (NdotL < 0.01) discard;
vec3 outcol = NdotL * col;
// World-space position
vec3 tmp = vec3(texc, z);
tmp = tmp * 2.0 - 1.0;
vec4 xpos = vec4(tmp, 1.0);
xpos = invprojview * xpos;
xpos.xyz /= xpos.w;
if (hasclouds == 1)
{
vec2 cloudcoord = (xpos.xz * 0.00833333) + wind;
float cloud = texture2D(cloudtex, cloudcoord).x;
//float cloud = step(0.5, cloudcoord.x) * step(0.5, cloudcoord.y);
outcol *= cloud;
}
// Shadows
vec3 shadowcoord = (shadowmat * vec4(xpos.xyz, 1.0)).xyz;
shadowcoord = (shadowcoord * 0.5) + vec3(0.5);
float movex = decdepth(texture2D(warpx, shadowcoord.xy));
float movey = decdepth(texture2D(warpy, shadowcoord.xy));
float dx = movex * 2.0 - 1.0;
float dy = movey * 2.0 - 1.0;
shadowcoord.xy += vec2(dx, dy);
vec4 shadowread = texture2D(shadowtex, shadowcoord.xy);
float shadowmapz = decdepth(vec4(shadowread.xyz, 0.0));
float moved = (abs(dx) + abs(dy)) * 0.5;
float bias = 0.002 * tan(acos(NdotL)); // According to the slope
bias += smoothstep(0.001, 0.1, moved) * 0.014; // According to the warping
bias = clamp(bias, 0.001, 0.014);
// This ID, and four IDs around this must match for a shadow pixel
float right = texture2D(shadowtex, shadowcoord.xy + vec2(shadowoffset, 0.0)).a;
float left = texture2D(shadowtex, shadowcoord.xy + vec2(-shadowoffset, 0.0)).a;
float up = texture2D(shadowtex, shadowcoord.xy + vec2(0.0, shadowoffset)).a;
float down = texture2D(shadowtex, shadowcoord.xy + vec2(0.0, -shadowoffset)).a;
float matching = ((right + left + up + down) * 0.25) - shadowread.a;
matching = abs(matching) * 400.0;
// If the ID is different, we're likely in shadow - cut the bias to cut peter panning
float off = 7.0 - step(abs(shadowread.a - depthread.a) - matching, 0.004) * 6.0;
bias /= off;
const float softness = 8.0; // How soft is the light?
float shadowed = step(shadowmapz + bias, shadowcoord.z);
float dist = (shadowcoord.z / shadowmapz) - 1.0;
float penumbra = dist * softness / gl_FragCoord.z;
penumbra *= shadowed;
/* outcol.r = (shadowcoord.z - shadowmapz) * 50.0;
outcol.g = moved;*/
gl_FragData[0] = vec4(outcol, 0.05);
gl_FragData[1] = vec4(shadowed, penumbra, shadowed, shadowed);
}

View File

@ -32,28 +32,25 @@ void main()
diffuseMaterial = texture2D (DecalTex, gl_TexCoord[0].st + vec2(delta1.x, 0.0));
diffuseLight = vec4(1.0, 1.0, 1.0, 1.0);
//if (lamberFactor < 0.7)
//{
// lamberFactor = 0.0;
//}
gl_FragColor = diffuseMaterial * (0.3 + lamberFactor*0.7);
vec3 col = diffuseMaterial.xyz * (0.3 + lamberFactor*0.7);
// specular (phong)
vec3 R = normalize(reflect(lightVec, normal));
float specular = max(dot(R,eyeVec),0.0);
float specular = max(dot(R, eyeVec), 0.0);
if (specular > 0.0)
{
// weak specular
specular = specular*specular;
specular = specular*specular;
float specular_weak = specular*0.05;
gl_FragColor += vec4(specular_weak, specular_weak, specular_weak, 0.0);
col += vec3(specular_weak, specular_weak, specular_weak);
// strong specular
specular = specular*specular;
float specular_strong = specular*0.3;
gl_FragColor += vec4(specular_strong, specular_strong, specular_strong, 0.0);
}
col += vec3(specular_strong, specular_strong, specular_strong);
float summed = dot(vec3(1.0), col) / 3.0;
float alpha = 0.9 + 0.1 * smoothstep(0.0, 1.0, summed);
gl_FragColor = vec4(col, alpha);
}

View File

@ -1,16 +1,23 @@
// Shader based on work by Fabien Sanglard
// Released under the terms of CC-BY 3.0
uniform float speed;
uniform float height;
uniform float length;
uniform vec3 lightdir;
varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;
uniform vec3 lightdir;
void main()
{
vec4 pos = gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
pos.y += (sin(pos.x/length + speed) + cos(pos.z/length + speed)) * height;
vec3 vertexPosition = vec3(gl_ModelViewMatrix * pos);
// Building the matrix Eye Space -> Tangent Space
vec3 n = normalize (gl_NormalMatrix * gl_Normal);
@ -18,8 +25,6 @@ void main()
vec3 t = normalize (gl_NormalMatrix * vec3(1.0, 0.0, 0.0)); // tangent
vec3 b = cross (n, t);
vec3 vertexPosition = vec3(gl_ModelViewMatrix * gl_Vertex);
// transform light and half angle vectors by tangent basis
vec3 v;
v.x = dot (lightdir, t);
@ -44,5 +49,7 @@ void main()
//normalize (v);
halfVec = v ;
gl_Position = ftransform();
gl_Position = gl_ModelViewProjectionMatrix * pos;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
}

View File

@ -1,75 +0,0 @@
// Shader based on work by Fabien Sanglard
// Released under the terms of CC-BY 3.0
uniform sampler2D BumpTex1; // Normal map 1
uniform sampler2D BumpTex2; // Normal map 2
uniform sampler2D DecalTex; //The texture
uniform vec2 delta1;
uniform vec2 delta2;
varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;
varying vec4 coord;
uniform vec4 fogColor;
uniform float fogFrom;
uniform float fogTo;
void main()
{
// lookup normal from normal map, move from [0,1] to [-1, 1] range, normalize
vec3 normal = 2.0 * texture2D (BumpTex1, gl_TexCoord[0].st + delta1).rgb - 1.0;
vec3 normal2 = 2.0 * texture2D (BumpTex2, gl_TexCoord[0].st + delta2).rgb - 1.0;
// scale normals
normal.y = 4.0*normal.y;
normal2.y = 4.0*normal2.y;
normal = (normalize(normal) + normalize(normal2))/2.0;
// compute diffuse lighting
float lamberFactor = max (dot (lightVec, normal), 0.0);
vec4 diffuseMaterial;
vec4 diffuseLight;
diffuseMaterial = texture2D (DecalTex, gl_TexCoord[0].st + vec2(delta1.x, 0.0));
diffuseLight = vec4(1.0, 1.0, 1.0, 1.0);
//if (lamberFactor < 0.7)
//{
// lamberFactor = 0.0;
//}
gl_FragColor = diffuseMaterial * (0.3 + lamberFactor*0.7);
// specular (phong)
vec3 R = normalize(reflect(lightVec, normal));
float specular = max(dot(R,eyeVec),0.0);
if (specular > 0.0)
{
// weak specular
specular = specular*specular;
specular = specular*specular;
float specular_weak = specular*0.05;
gl_FragColor += vec4(specular_weak, specular_weak, specular_weak, 0.0);
// strong specular
specular = specular*specular;
float specular_strong = specular*0.3;
gl_FragColor += vec4(specular_strong, specular_strong, specular_strong, 0.0);
}
if (coord.z > fogTo)
{
gl_FragColor = fogColor;
}
else if (coord.z > fogFrom)
{
float fogIntensity = (coord.z - fogFrom) / (fogTo - fogFrom);
gl_FragColor = fogIntensity*fogColor + (1.0 - fogIntensity)*gl_FragColor;
}
}

View File

@ -1,49 +0,0 @@
// Shader based on work by Fabien Sanglard
// Released under the terms of CC-BY 3.0
varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;
varying vec4 coord;
uniform vec3 lightdir;
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
// Building the matrix Eye Space -> Tangent Space
vec3 n = normalize (gl_NormalMatrix * gl_Normal);
// gl_MultiTexCoord1.xyz
vec3 t = normalize (gl_NormalMatrix * vec3(1.0, 0.0, 0.0)); // tangent
vec3 b = cross (n, t);
vec3 vertexPosition = vec3(gl_ModelViewMatrix * gl_Vertex);
// transform light and half angle vectors by tangent basis
vec3 v;
v.x = dot (lightdir, t);
v.y = dot (lightdir, b);
v.z = dot (lightdir, n);
lightVec = normalize (v);
vertexPosition = normalize(vertexPosition);
eyeVec = normalize(-vertexPosition); // we are in Eye Coordinates, so EyePos is (0,0,0)
// Normalize the halfVector to pass it to the fragment shader
// No need to divide by two, the result is normalized anyway.
// vec3 halfVector = normalize((vertexPosition + lightDir) / 2.0);
vec3 halfVector = normalize(vertexPosition + lightdir);
v.x = dot (halfVector, t);
v.y = dot (halfVector, b);
v.z = dot (halfVector, n);
// No need to normalize, t,b,n and halfVector are normal vectors.
//normalize (v);
halfVec = v ;
gl_Position = ftransform();
coord = gl_Position;
}

4
data/shaders/white.frag Normal file
View File

@ -0,0 +1,4 @@
void main()
{
gl_FragColor = vec4(1.0);
}

View File

@ -135,6 +135,9 @@
<steer disable-while-unskid="false"
camera-follow-skid="true" />
<!-- Glow colors for the items -->
<glow-colors nitro="0 0 255" box="255 0 0" />
<!-- Default values for all karts
============================ -->
<general-kart-defaults>

21
doc/graphics_views.txt Normal file
View File

@ -0,0 +1,21 @@
Graphics debug views
====================
There are some graphics debug views, to be used both by artists when developing,
and by users when reporting bugs.
These should be available in normal (non-artist) mode
to enable easier bug reports (go there, press this key, screenshot)
without requiring editing the UTF-32 config files (which is inconvenient, most editors
do not support that weird encoding).
They don't give gameplay advantages like the item keys, so there should be little harm
leaving them available. Accidental keypresses ought to be minimized by their location.
Home - wireframe view
End - mipmap visualization (is a texture too high or low resolution, red = too high)
Del - normal view
PgDown - SSAO view
PgUp - light view
Ins - shadow view
ScrlLock - displacement view

157
doc/graphics_xml.txt Normal file
View File

@ -0,0 +1,157 @@
Graphics GSOC XML additions
===========================
This document will list in depth all new XML values added during the graphics GSOC, for use
by the blender exporter scripts.
Glow colors
-----------
The glow colors for nitro bottles and boxes are settable in stk_config.xml.
They are three-value RGB colors.
Example: <glow-colors nitro="0 0 255" box="255 0 0" />
Particle wind
-------------
Particles may be affected by wind. This is used with the snow particles.
Flips is a boolean controlling whether each particle will spin about its own two axis.
It is only applicable to symmetric textures, such as snow flakes.
Speed is a float in no real units.
Example: <wind speed="0.16" flips="Y" />
Forced bloom objects
--------------------
Any object may be marked as forced bloom. This will include the object in the bloom pass
regardless of its brightness.
Example: forcedbloom="Y" inside the <object> tag, in scene.xml.
Forced bloom objects may optionally include a multiplier, ranging from 0.5 to 10:
bloompower="2.5"
Glowing objects
---------------
Any object may be marked as glowing. The glow is a RGB value.
Example: glow="0 255 0" inside the <object> tag, in scene.xml.
Caustics
--------
A material effect, ie GE_CAUSTICS, to mark a texture as receiving caustics. To be used
for the ocean floor, puddle floor, etc.
Example: graphics-effect="caustics" in materials.xml.
Refractions/reflections
-----------------------
A per-object boolean flag, typically set for subsea windows or the ocean surface.
Example: displacing="Y" in the <object> tag in scene.xml.
Per-track tags
--------------
These are all specified inside track.xml, among the track's author, music, etc.
Cloud shadows
-------------
Boolean whether to have the sun blocked by cloud shadows, moving with the wind.
Disabled by default.
The effect is completely fake, doesn't correspond to any real or simulated clouds, but
nobody's checking, so it looks nice.
Example: clouds="Y" inside the <track> tag.
Bloom
-----
Boolean whether to enable global bloom for this track. Enabled by default.
Example: bloom="Y" inside the <track> tag.
Bloom threshold
---------------
Float that specifies the minimum luminance needed for a pixel to participate in the bloom.
The default is 0.75.
Example: bloom-threshold="0.75"
Lens flare
----------
Boolean that specifies whether a lens flare is shown when the player looks at the sun.
The strength and angle depend on the relation of the camera to the sun. Disabled by default.
Example: lens-flare="Y"
Dynamic shadows
---------------
Boolean on whether this track should use dynamic shadows. Enabled by default.
If disabled, the fallback fake kart shadows will be used.
Example: shadows="N"
God rays
--------
Boolean on rendering god rays when the player looks at the sun. Disabled by default.
Example: god-rays="Y"
Displacement speed
------------------
Float on the relative speed of any displacing objects in this level. Default 1.0.
2.0 = double speed, 0.5 = half speed, etc.
Example: displacement-speed="1.5"
Caustics speed
--------------
Float on the relative speed of any caustics objects in this level. Default 1.0.
2.0 = double speed, 0.5 = half speed, etc.
Example: caustics-speed="1.5"
Fog
---
The density tag was removed (it was unused anyway).
The max, height start, and height end tags were added.
fog-max: float capping the amount of fog to apply, default 1.0.
fog-start-height: minimum height of fog, default 0.0.
fog-end-height: maximum height of fog, default 100.0.
The fog scales smoothly according to both the height, and the distance from
camera.

44
doc/pipeline_overview.txt Normal file
View File

@ -0,0 +1,44 @@
New pipeline overview
=====================
Organized by RTTs
-----------------
To color:
- initialize the glow representations (no rendering yet)
- render the 3d skybox, if any (includes the usual skybox)
To the MRT (color, normals, depth):
- solids
To quarter1:
- glowmap
To various shadow maps:
- shadows
To tmp1:
- lights
To color:
- lights from tmp1 are multiplicatively blended
- skybox if there is no 3d skybox
- lens flare/god rays occlusion query (no rendering)
- solid post-processing
- transparents
To displace:
- displacing nodes, if any
To the screen:
- the post-processing chain
- GUI
Organized by passes
-------------------
Init: glow init -> 3d skybox
Main: solids -> glows -> shadows -> lights -> occlusion query -> solid PP
Transparent: transparents -> displacing -> PP
GUI: gui

View File

@ -25,12 +25,16 @@ src/config/player.cpp
src/config/saved_grand_prix.cpp
src/config/stk_config.cpp
src/config/user_config.cpp
src/graphics/callbacks.cpp
src/graphics/camera.cpp
src/graphics/CBatchingMesh.cpp
src/graphics/explosion.cpp
src/graphics/glow.cpp
src/graphics/hardware_skinning.cpp
src/graphics/hit_sfx.cpp
src/graphics/irr_driver.cpp
src/graphics/lens_flare.cpp
src/graphics/light.cpp
src/graphics/lod_node.cpp
src/graphics/material.cpp
src/graphics/material_manager.cpp
@ -43,11 +47,19 @@ src/graphics/per_camera_node.cpp
src/graphics/post_processing.cpp
src/graphics/rain.cpp
src/graphics/referee.cpp
src/graphics/render.cpp
src/graphics/rtts.cpp
src/graphics/screenquad.cpp
src/graphics/shaders.cpp
src/graphics/shadow.cpp
src/graphics/shadow_importance.cpp
src/graphics/show_curve.cpp
src/graphics/skid_marks.cpp
src/graphics/slip_stream.cpp
src/graphics/stars.cpp
src/graphics/sun.cpp
src/graphics/water.cpp
src/graphics/wind.cpp
src/guiengine/abstract_state_manager.cpp
src/guiengine/abstract_top_level_container.cpp
src/guiengine/CGUISpriteBank.cpp
@ -234,6 +246,7 @@ src/tracks/track_object_presentation.cpp
src/tracks/track_sector.cpp
src/utils/constants.cpp
src/utils/crash_reporting.cpp
src/utils/helpers.cpp
src/utils/leak_check.cpp
src/utils/log.cpp
src/utils/profiler.cpp
@ -274,17 +287,24 @@ src/config/player.hpp
src/config/saved_grand_prix.hpp
src/config/stk_config.hpp
src/config/user_config.hpp
src/graphics/callbacks.hpp
src/graphics/camera.hpp
src/graphics/CBatchingMesh.hpp
src/graphics/explosion.hpp
src/graphics/glow.hpp
src/graphics/glwrap.hpp
src/graphics/hardware_skinning.hpp
src/graphics/hit_effect.hpp
src/graphics/hit_sfx.hpp
src/graphics/irr_driver.hpp
src/graphics/large_mesh_buffer.hpp
src/graphics/lens_flare.hpp
src/graphics/light.hpp
src/graphics/lod_node.hpp
src/graphics/material.hpp
src/graphics/material_manager.hpp
src/graphics/mesh_tools.hpp
src/graphics/mlaa_areamap.hpp
src/graphics/moving_texture.hpp
src/graphics/particle_emitter.hpp
src/graphics/particle_kind.hpp
@ -293,11 +313,18 @@ src/graphics/per_camera_node.hpp
src/graphics/post_processing.hpp
src/graphics/rain.hpp
src/graphics/referee.hpp
src/graphics/rtts.hpp
src/graphics/screenquad.hpp
src/graphics/shaders.hpp
src/graphics/shadow.hpp
src/graphics/shadow_importance.hpp
src/graphics/show_curve.hpp
src/graphics/skid_marks.hpp
src/graphics/slip_stream.hpp
src/graphics/stars.hpp
src/graphics/sun.hpp
src/graphics/water.hpp
src/graphics/wind.hpp
src/guiengine/abstract_state_manager.hpp
src/guiengine/abstract_top_level_container.hpp
src/guiengine/engine.hpp
@ -499,6 +526,7 @@ src/tracks/track_object_presentation.hpp
src/tracks/track_sector.hpp
src/utils/aligned_array.hpp
src/utils/constants.hpp
src/utils/helpers.hpp
src/utils/interpolation_array.hpp
src/utils/crash_reporting.hpp
src/utils/leak_check.hpp
@ -512,4 +540,5 @@ src/utils/synchronised.hpp
src/utils/time.hpp
src/utils/translation.hpp
src/utils/vec3.hpp
src/utils/vs.hpp
)

View File

@ -69,10 +69,14 @@ supertuxkart_SOURCES = \
config/device_config.hpp \
graphics/CBatchingMesh.cpp \
graphics/CBatchingMesh.hpp \
graphics/callbacks.cpp \
graphics/callbacks.hpp \
graphics/camera.cpp \
graphics/camera.hpp \
graphics/explosion.cpp \
graphics/explosion.hpp \
graphics/glow.cpp \
graphics/glow.hpp \
graphics/hardware_skinning.cpp \
graphics/hardware_skinning.hpp \
graphics/hit_effect.hpp \
@ -80,6 +84,11 @@ supertuxkart_SOURCES = \
graphics/hit_sfx.hpp \
graphics/irr_driver.cpp \
graphics/irr_driver.hpp \
graphics/large_mesh_buffer.hpp \
graphics/lens_flare.cpp \
graphics/lens_flare.hpp \
graphics/light.hpp \
graphics/light.cpp \
graphics/lod_node.cpp \
graphics/lod_node.hpp \
graphics/material.cpp \
@ -102,10 +111,19 @@ supertuxkart_SOURCES = \
graphics/post_processing.hpp \
graphics/rain.cpp \
graphics/rain.hpp \
graphics/render.cpp \
graphics/referee.cpp \
graphics/referee.hpp \
graphics/rtts.hpp \
graphics/rtts.cpp \
graphics/screenquad.cpp \
graphics/screenquad.hpp \
graphics/shaders.cpp \
graphics/shaders.hpp \
graphics/shadow.cpp \
graphics/shadow.hpp \
graphics/shadow_importance.cpp \
graphics/shadow_importance.hpp \
graphics/show_curve.cpp \
graphics/show_curve.hpp \
graphics/skid_marks.cpp \
@ -114,6 +132,12 @@ supertuxkart_SOURCES = \
graphics/slip_stream.hpp \
graphics/stars.cpp \
graphics/stars.hpp \
graphics/sun.hpp \
graphics/sun.cpp \
graphics/water.hpp \
graphics/water.cpp \
graphics/wind.hpp \
graphics/wind.cpp \
guiengine/CGUISpriteBank.cpp \
guiengine/CGUISpriteBank.h \
guiengine/abstract_state_manager.cpp \
@ -496,6 +520,8 @@ supertuxkart_SOURCES = \
utils/aligned_array.hpp \
utils/constants.hpp \
utils/constants.cpp \
utils/helpers.hpp \
utils/helpers.cpp \
utils/leak_check.cpp \
utils/leak_check.hpp \
utils/log.cpp \
@ -518,7 +544,8 @@ supertuxkart_SOURCES = \
utils/utf8/core.h \
utils/utf8/unchecked.h \
utils/vec3.cpp \
utils/vec3.hpp
utils/vec3.hpp \
utils/vs.hpp
# Link in the specific gcc 4.1 bug work around
supertuxkart_LDADD = \

View File

@ -24,14 +24,7 @@
#include <errno.h>
#include <stdio.h>
#include <string>
#if defined(WIN32) && !defined(__CYGWIN__)
# include <windows.h>
# define isnan _isnan
#else
# include <sys/time.h>
# include <math.h>
#endif
#include <math.h>
#include "addons/news_manager.hpp"
#include "addons/request.hpp"
@ -42,6 +35,7 @@
#include "utils/string_utils.hpp"
#include "utils/time.hpp"
#include "utils/translation.hpp"
#include "utils/vs.hpp"
// ----------------------------------------------------------------------------
/** Create a thread that handles all network functions independent of the

View File

@ -21,14 +21,10 @@
#include "animations/ipo.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "utils/vs.hpp"
#include <algorithm>
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define isnan _isnan
#else
# include <math.h>
#endif
#include <math.h>
AnimationBase::AnimationBase(const XMLNode &node)

View File

@ -19,15 +19,11 @@
#include "animations/ipo.hpp"
#include "io/xml_node.hpp"
#include "utils/vs.hpp"
#include <string.h>
#include <algorithm>
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define isnan _isnan
#else
# include <math.h>
#endif
#include <math.h>
const std::string Ipo::m_all_channel_names[IPO_MAX] =
{"LocX", "LocY", "LocZ", "LocXYZ",

View File

@ -181,6 +181,13 @@ void STKConfig::init_defaults()
m_disable_steer_while_unskid = false;
m_camera_follow_skid = false;
m_nitro_glow_color[0] = 1.0f;
m_nitro_glow_color[1] = 1.0f;
m_nitro_glow_color[2] = 1.0f;
m_box_glow_color[0] = 1.0f;
m_box_glow_color[1] = 1.0f;
m_box_glow_color[2] = 1.0f;
m_score_increase.clear();
m_leader_intervals.clear();
m_switch_items.clear();
@ -362,6 +369,25 @@ void STKConfig::getAllData(const XMLNode * root)
replay_node->get("delta-pos", &m_replay_delta_pos2 );
replay_node->get("delta-t", &m_replay_dt );
}
if(const XMLNode *colors = root->getNode("glow-colors"))
{
video::SColor tmpcol;
if (colors->get("nitro", &tmpcol))
{
m_nitro_glow_color[0] = tmpcol.getRed() / 255.0f;
m_nitro_glow_color[1] = tmpcol.getGreen() / 255.0f;
m_nitro_glow_color[2] = tmpcol.getBlue() / 255.0f;
}
if (colors->get("box", &tmpcol))
{
m_box_glow_color[0] = tmpcol.getRed() / 255.0f;
m_box_glow_color[1] = tmpcol.getGreen() / 255.0f;
m_box_glow_color[2] = tmpcol.getBlue() / 255.0f;
}
}
// Get the default KartProperties
// ------------------------------
const XMLNode *node = root -> getNode("general-kart-defaults");

View File

@ -148,6 +148,11 @@ public:
* be generated. */
float m_replay_delta_angle;
/** Colors for glows */
float m_nitro_glow_color[3];
float m_box_glow_color[3];
private:
/** True if stk_config has been loaded. This is necessary if the
* --stk-config command line parameter has been specified to avoid

View File

@ -510,10 +510,6 @@ namespace UserConfigParams
#define FBO_DEFAULT true
#endif
PARAM_PREFIX BoolUserConfigParam m_fbo
PARAM_DEFAULT( BoolUserConfigParam(FBO_DEFAULT, "fbo",
&m_graphics_quality, "Use frame buffer objects (FBOs)") );
PARAM_PREFIX BoolUserConfigParam m_graphical_effects
PARAM_DEFAULT( BoolUserConfigParam(true, "anim_gfx",
&m_graphics_quality, "Scenery animations") );
@ -552,11 +548,22 @@ namespace UserConfigParams
PARAM_DEFAULT( BoolUserConfigParam(true, "pixel_shaders",
&m_graphics_quality,
"Whether to enable pixel shaders (splatting, normal maps, ...)") );
PARAM_PREFIX BoolUserConfigParam m_postprocess_enabled
PARAM_PREFIX BoolUserConfigParam m_motionblur
PARAM_DEFAULT( BoolUserConfigParam(false,
"postprocess_enabled", &m_graphics_quality,
"Whether post-processing (motion blur...) should "
"be enabled") );
"motionblur_enabled", &m_graphics_quality,
"Whether motion blur should be enabled") );
PARAM_PREFIX BoolUserConfigParam m_mlaa
PARAM_DEFAULT( BoolUserConfigParam(false,
"mlaa", &m_graphics_quality,
"Whether MLAA should be enabled") );
PARAM_PREFIX IntUserConfigParam m_ssao
PARAM_DEFAULT( IntUserConfigParam(0,
"ssao", &m_graphics_quality,
"Whether SSAO is enabled (0 = disabled, 1 = low, 2 = high") );
PARAM_PREFIX IntUserConfigParam m_shadows
PARAM_DEFAULT( IntUserConfigParam(0,
"shadows", &m_graphics_quality,
"Whether shadows are enabled (0 = disabled, 1 = low, 2 = high") );
// ---- Misc
PARAM_PREFIX BoolUserConfigParam m_cache_overworld

775
src/graphics/callbacks.cpp Normal file
View File

@ -0,0 +1,775 @@
// SuperTuxKart - a fun racing game with go-kart
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/callbacks.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/wind.hpp"
#include "guiengine/engine.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
#include "utils/helpers.hpp"
using namespace video;
using namespace core;
//-------------------------------------
void NormalMapProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
s32 decaltex = 0;
srv->setPixelShaderConstant("DecalTex", &decaltex, 1);
s32 bumptex = 1;
srv->setPixelShaderConstant("BumpTex", &bumptex, 1);
s32 lightmapTex = (m_with_lightmap ? 2 : 0);
srv->setPixelShaderConstant("LightMapTex", &lightmapTex, 1);
s32 hasLightMap = (m_with_lightmap ? 1 : 0);
srv->setPixelShaderConstant("HasLightMap", &hasLightMap, 1);
// We could calculate light direction as coming from the sun (then we'd need to
// transform it into camera space). But I find that pretending light
// comes from the camera gives good results
const float lightdir[] = {0.1852f, -0.1852f, -0.9259f};
srv->setVertexShaderConstant("lightdir", lightdir, 3);
firstdone = true;
}
}
//-------------------------------------
void WaterShaderProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
float strength = time;
strength = 1.4f - fabsf(noise2d(strength / 30.0f + 133)) * 0.8f;
m_dx_1 += GUIEngine::getLatestDt() * m_water_shader_speed_1 * strength;
m_dy_1 += GUIEngine::getLatestDt() * m_water_shader_speed_1 * strength;
m_dx_2 += GUIEngine::getLatestDt() * m_water_shader_speed_2 * strength;
m_dy_2 -= GUIEngine::getLatestDt() * m_water_shader_speed_2 * strength;
if (m_dx_1 > 1.0f) m_dx_1 -= 1.0f;
if (m_dy_1 > 1.0f) m_dy_1 -= 1.0f;
if (m_dx_2 > 1.0f) m_dx_2 -= 1.0f;
if (m_dy_2 < 0.0f) m_dy_2 += 1.0f;
const float d1[2] = { m_dx_1, m_dy_1 };
const float d2[2] = { m_dx_2, m_dy_2 };
srv->setVertexShaderConstant("delta1", d1, 2);
srv->setVertexShaderConstant("delta2", d2, 2);
const float speed = irr_driver->getDevice()->getTimer()->getTime() / m_speed;
const float height = m_height * strength;
srv->setVertexShaderConstant("height", &height, 1);
srv->setVertexShaderConstant("speed", &speed, 1);
srv->setVertexShaderConstant("length", &m_length, 1);
// Can't use the firstdone optimization, as the callback is shared
//if (!firstdone)
{
s32 decaltex = 0;
srv->setPixelShaderConstant("DecalTex", &decaltex, 1);
s32 bumptex = 1;
srv->setPixelShaderConstant("BumpTex1", &bumptex, 1);
bumptex = 2;
srv->setPixelShaderConstant("BumpTex2", &bumptex, 1);
// Calculate light direction as coming from the sun.
matrix4 normalm = srv->getVideoDriver()->getTransform(ETS_VIEW);
normalm.makeInverse();
normalm = normalm.getTransposed();
vector3df tmp = m_sunpos;
normalm.transformVect(tmp);
tmp.normalize();
const float lightdir[] = {tmp.X, tmp.Y, tmp.Z};
srv->setVertexShaderConstant("lightdir", lightdir, 3);
firstdone = true;
}
}
//-------------------------------------
void GrassShaderProvider::OnSetConstants(IMaterialRendererServices *srv, int userData)
{
IVideoDriver * const drv = srv->getVideoDriver();
const core::vector3df pos = drv->getTransform(ETS_WORLD).getTranslation();
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
float strength = (pos.X + pos.Y + pos.Z) * 1.2f + time * m_speed;
strength = noise2d(strength / 10.0f) * m_amplitude * 5;
// * 5 is to work with the existing amplitude values.
// Pre-multiply on the cpu
vector3df wind = irr_driver->getWind() * strength;
srv->setVertexShaderConstant("windDir", &wind.X, 3);
if (!firstdone)
{
s32 tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void SplattingProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float camfar = irr_driver->getSceneManager()->getActiveCamera()->getFarValue();
srv->setVertexShaderConstant("far", &camfar, 1);
// The normal is transformed by the inverse transposed world matrix
// because we want world-space normals
matrix4 invtworldm = irr_driver->getVideoDriver()->getTransform(ETS_WORLD);
invtworldm.makeInverse();
invtworldm = invtworldm.getTransposed();
srv->setVertexShaderConstant("invtworldm", invtworldm.pointer(), 16);
float objectid = 0;
const stringc name = mat.TextureLayer[0].Texture->getName().getPath();
objectid = shash8((const u8 *) name.c_str(), name.size()) / 255.0f;
srv->setVertexShaderConstant("objectid", &objectid, 1);
if (!firstdone)
{
s32 tex_layout = 1;
srv->setPixelShaderConstant("tex_layout", &tex_layout, 1);
s32 tex_detail0 = 2;
srv->setPixelShaderConstant("tex_detail0", &tex_detail0, 1);
s32 tex_detail1 = 3;
srv->setPixelShaderConstant("tex_detail1", &tex_detail1, 1);
s32 tex_detail2 = 4;
srv->setPixelShaderConstant("tex_detail2", &tex_detail2, 1);
s32 tex_detail3 = 5;
srv->setPixelShaderConstant("tex_detail3", &tex_detail3, 1);
firstdone = true;
}
}
//-------------------------------------
void BubbleEffectProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float start = fabsf(mat.MaterialTypeParam2);
const bool visible = mat.MaterialTypeParam2 > 0;
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
float transparency;
const float diff = (time - start) / 3.0f;
if (visible)
{
transparency = diff;
}
else
{
transparency = 1.0 - diff;
}
transparency = clampf(transparency, 0, 1);
srv->setVertexShaderConstant("time", &time, 1);
srv->setVertexShaderConstant("transparency", &transparency, 1);
}
//-------------------------------------
void RainEffectProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float screenw = UserConfigParams::m_width;
const float time = irr_driver->getDevice()->getTimer()->getTime() / 90.0f;
const matrix4 viewm = srv->getVideoDriver()->getTransform(ETS_VIEW);
const vector3df campos = irr_driver->getSceneManager()->getActiveCamera()->getPosition();
srv->setVertexShaderConstant("screenw", &screenw, 1);
srv->setVertexShaderConstant("time", &time, 1);
srv->setVertexShaderConstant("viewm", viewm.pointer(), 16);
srv->setVertexShaderConstant("campos", &campos.X, 3);
}
//-------------------------------------
void SnowEffectProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
srv->setVertexShaderConstant("time", &time, 1);
}
//-------------------------------------
void MotionBlurProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
// We need the maximum texture coordinates:
float max_tex_height = m_maxheight[m_current_camera];
srv->setPixelShaderConstant("max_tex_height", &max_tex_height, 1);
// Scale the boost time to get a usable boost amount:
float boost_amount = m_boost_time[m_current_camera] * 0.7f;
// Especially for single screen the top of the screen is less blurred
// in the fragment shader by multiplying the blurr factor by
// (max_tex_height - texcoords.t), where max_tex_height is the maximum
// texture coordinate (1.0 or 0.5). In split screen this factor is too
// small (half the value compared with non-split screen), so we
// multiply this by 2.
if(Camera::getNumCameras() > 1)
boost_amount *= 2.0f;
srv->setPixelShaderConstant("boost_amount", &boost_amount, 1);
srv->setPixelShaderConstant("center",
&(m_center[m_current_camera].X), 2);
srv->setPixelShaderConstant("direction",
&(m_direction[m_current_camera].X), 2);
// Use a radius of 0.15 when showing a single kart, otherwise (2-4 karts
// on splitscreen) use only 0.75.
float radius = Camera::getNumCameras()==1 ? 0.15f : 0.075f;
srv->setPixelShaderConstant("mask_radius", &radius, 1);
const int texunit = 0;
srv->setPixelShaderConstant("color_buffer", &texunit, 1);
}
//-------------------------------------
void GaussianBlurProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("pixel", m_pixel, 2);
}
//-------------------------------------
void MipVizProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const ITexture * const tex = mat.TextureLayer[0].Texture;
const int notex = (mat.TextureLayer[0].Texture == NULL);
srv->setVertexShaderConstant("notex", &notex, 1);
if (!tex) return;
const dimension2du size = tex->getSize();
const float texsize[2] = {
size.Width,
size.Height
};
srv->setVertexShaderConstant("texsize", texsize, 2);
}
//-------------------------------------
void ColorizeProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("col", m_color, 3);
}
//-------------------------------------
void GlowProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("res", m_res, 2);
}
//-------------------------------------
void ObjectPassProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float camfar = irr_driver->getSceneManager()->getActiveCamera()->getFarValue();
srv->setVertexShaderConstant("far", &camfar, 1);
// The normal is transformed by the inverse transposed world matrix
// because we want world-space normals
matrix4 invtworldm = irr_driver->getVideoDriver()->getTransform(ETS_WORLD);
invtworldm.makeInverse();
invtworldm = invtworldm.getTransposed();
srv->setVertexShaderConstant("invtworldm", invtworldm.pointer(), 16);
const int hastex = mat.TextureLayer[0].Texture != NULL;
srv->setVertexShaderConstant("hastex", &hastex, 1);
const int haslightmap = mat.TextureLayer[1].Texture != NULL;
srv->setVertexShaderConstant("haslightmap", &haslightmap, 1);
float objectid = 0;
if (hastex)
{
const stringc name = mat.TextureLayer[0].Texture->getName().getPath();
objectid = shash8((const u8 *) name.c_str(), name.size()) / 255.0f;
}
srv->setVertexShaderConstant("objectid", &objectid, 1);
//if (!firstdone)
// Can't use the firstdone optimization, as this callback is used for multiple shaders
{
int tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("lighttex", &tex, 1);
}
}
//-------------------------------------
void LightBlendProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const SColorf s = irr_driver->getSceneManager()->getAmbientLight();
float ambient[3] = { s.r, s.g, s.b };
srv->setVertexShaderConstant("ambient", ambient, 3);
int spectex = 1;
srv->setVertexShaderConstant("spectex", &spectex, 1);
}
//-------------------------------------
void PointLightProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("screen", m_screen, 2);
srv->setVertexShaderConstant("spec", &m_specular, 1);
srv->setVertexShaderConstant("col", m_color, 3);
srv->setVertexShaderConstant("campos", m_campos, 3);
srv->setVertexShaderConstant("center", m_pos, 3);
srv->setVertexShaderConstant("r", &m_radius, 1);
srv->setVertexShaderConstant("invprojview", m_invprojview.pointer(), 16);
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("ntex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("dtex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void SunLightProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const int hasclouds = World::getWorld()->getTrack()->hasClouds() &&
UserConfigParams::m_weather_effects;
srv->setVertexShaderConstant("screen", m_screen, 2);
srv->setVertexShaderConstant("col", m_color, 3);
srv->setVertexShaderConstant("center", m_pos, 3);
srv->setVertexShaderConstant("invprojview", m_invprojview.pointer(), 16);
srv->setVertexShaderConstant("hasclouds", &hasclouds, 1);
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
float strength = time;
strength = fabsf(noise2d(strength / 10.0f)) * 0.003f;
const vector3df winddir = irr_driver->getWind() * strength;
m_wind[0] += winddir.X;
m_wind[1] += winddir.Z;
srv->setVertexShaderConstant("wind", m_wind, 2);
if (UserConfigParams::m_shadows)
{
srv->setVertexShaderConstant("shadowmat", m_shadowmat.pointer(), 16);
}
// Can't use the firstdone optimization, as this callback is used for multiple shaders
//if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("ntex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("dtex", &tex, 1);
tex = 2;
srv->setVertexShaderConstant("cloudtex", &tex, 1);
tex = 3;
srv->setVertexShaderConstant("shadowtex", &tex, 1);
tex = 4;
srv->setVertexShaderConstant("warpx", &tex, 1);
tex = 5;
srv->setVertexShaderConstant("warpy", &tex, 1);
const float shadowoffset = 1.0f / irr_driver->getRTT(RTT_SHADOW)->getSize().Width;
srv->setVertexShaderConstant("shadowoffset", &shadowoffset, 1);
firstdone = true;
}
}
//-------------------------------------
void BloomProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("low", &m_threshold, 1);
}
//-------------------------------------
void MLAAColor1Provider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
const float pixels[2] = {
1.0f / UserConfigParams::m_width,
1.0f / UserConfigParams::m_height
};
srv->setPixelShaderConstant("PIXEL_SIZE", pixels, 2);
firstdone = true;
}
}
//-------------------------------------
void MLAABlend2Provider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
const float pixels[2] = {
1.0f / UserConfigParams::m_width,
1.0f / UserConfigParams::m_height
};
srv->setPixelShaderConstant("PIXEL_SIZE", pixels, 2);
int tex = 0;
srv->setPixelShaderConstant("edgesMap", &tex, 1);
tex = 1;
srv->setPixelShaderConstant("areaMap", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void MLAANeigh3Provider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
const float pixels[2] = {
1.0f / UserConfigParams::m_width,
1.0f / UserConfigParams::m_height
};
srv->setPixelShaderConstant("PIXEL_SIZE", pixels, 2);
int tex = 0;
srv->setPixelShaderConstant("blendMap", &tex, 1);
tex = 1;
srv->setPixelShaderConstant("colorMap", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void SSAOProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
int tex = 0;
srv->setPixelShaderConstant("tex", &tex, 1);
tex = 1;
srv->setPixelShaderConstant("oldtex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void GodRayProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setPixelShaderConstant("sunpos", m_sunpos, 2);
}
//-------------------------------------
void ShadowPassProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const int hastex = mat.TextureLayer[0].Texture != NULL;
srv->setVertexShaderConstant("hastex", &hastex, 1);
int viz = irr_driver->getShadowViz();
srv->setVertexShaderConstant("viz", &viz, 1);
int wireframe = mat.Wireframe;
srv->setVertexShaderConstant("wireframe", &wireframe, 1);
float objectid = 0;
if (hastex)
{
const stringc name = mat.TextureLayer[0].Texture->getName().getPath();
objectid = shash8((const u8 *) name.c_str(), name.size()) / 255.0f;
}
srv->setVertexShaderConstant("objectid", &objectid, 1);
//if (!firstdone)
// Can't use the firstdone optimization, as this callback is used for multiple shaders
{
int tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("warpx", &tex, 1);
tex = 2;
srv->setVertexShaderConstant("warpy", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void ShadowImportanceProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("shadowmat", m_shadowmat.pointer(), 16);
srv->setVertexShaderConstant("ipvmat", m_invprojview.pointer(), 16);
srv->setVertexShaderConstant("campos", m_campos, 3);
int low = UserConfigParams::m_shadows == 1;
srv->setVertexShaderConstant("low", &low, 1);
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("ntex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("dtex", &tex, 1);
tex = 2;
srv->setVertexShaderConstant("ctex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void CollapseProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("pixel", m_pixel, 2);
srv->setVertexShaderConstant("multi", m_multi, 2);
srv->setVertexShaderConstant("size", &m_size, 1);
//if (!firstdone)
// Can't use the firstdone optimization, as this callback is used for multiple shaders
{
int tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("oldtex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void BloomPowerProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("power", &m_power, 1);
}
//-------------------------------------
void MultiplyProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("tex1", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("tex2", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void ShadowGenProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("halft", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("quarter", &tex, 1);
tex = 2;
srv->setVertexShaderConstant("eighth", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void CausticsProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
const float speed = World::getWorld()->getTrack()->getCausticsSpeed();
float strength = time;
strength = fabsf(noise2d(strength / 10.0f)) * 0.006f + 0.001f;
vector3df wind = irr_driver->getWind() * strength * speed;
m_dir[0] += wind.X;
m_dir[1] += wind.Z;
strength = time * 0.56f + sinf(time);
strength = fabsf(noise2d(0.0, strength / 6.0f)) * 0.0095f + 0.001f;
wind = irr_driver->getWind() * strength * speed;
wind.rotateXZBy(cosf(time));
m_dir2[0] += wind.X;
m_dir2[1] += wind.Z;
srv->setVertexShaderConstant("dir", m_dir, 2);
srv->setVertexShaderConstant("dir2", m_dir2, 2);
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("caustictex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void DisplaceProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
const float speed = World::getWorld()->getTrack()->getDisplacementSpeed();
float strength = time;
strength = fabsf(noise2d(strength / 10.0f)) * 0.006f + 0.002f;
vector3df wind = irr_driver->getWind() * strength * speed;
m_dir[0] += wind.X;
m_dir[1] += wind.Z;
strength = time * 0.56f + sinf(time);
strength = fabsf(noise2d(0.0, strength / 6.0f)) * 0.0095f + 0.0025f;
wind = irr_driver->getWind() * strength * speed;
wind.rotateXZBy(cosf(time));
m_dir2[0] += wind.X;
m_dir2[1] += wind.Z;
srv->setVertexShaderConstant("dir", m_dir, 2);
srv->setVertexShaderConstant("dir2", m_dir2, 2);
srv->setVertexShaderConstant("screen", m_screen, 2);
}
//-------------------------------------
void PPDisplaceProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
int viz = irr_driver->getDistortViz();
srv->setPixelShaderConstant("viz", &viz, 1);
if (!firstdone)
{
int tex = 0;
srv->setPixelShaderConstant("tex", &tex, 1);
tex = 1;
srv->setPixelShaderConstant("dtex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void FogProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const Track * const track = World::getWorld()->getTrack();
// This function is only called once per frame - thus no need for setters.
const float fogmax = track->getFogMax();
const float startH = track->getFogStartHeight();
const float endH = track->getFogEndHeight();
const float start = track->getFogStart();
const float end = track->getFogEnd();
const SColor tmpcol = track->getFogColor();
const float col[3] = { tmpcol.getRed() / 255.0f,
tmpcol.getGreen() / 255.0f,
tmpcol.getBlue() / 255.0f };
srv->setPixelShaderConstant("fogmax", &fogmax, 1);
srv->setPixelShaderConstant("startH", &startH, 1);
srv->setPixelShaderConstant("endH", &endH, 1);
srv->setPixelShaderConstant("start", &start, 1);
srv->setPixelShaderConstant("end", &end, 1);
srv->setPixelShaderConstant("col", col, 3);
srv->setVertexShaderConstant("ipvmat", m_invprojview.pointer(), 16);
srv->setVertexShaderConstant("campos", m_campos, 3);
}

712
src/graphics/callbacks.hpp Normal file
View File

@ -0,0 +1,712 @@
// SuperTuxKart - a fun racing game with go-kart
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_CALLBACKS_HPP
#define HEADER_CALLBACKS_HPP
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include <IShaderConstantSetCallBack.h>
#include <SMaterial.h>
#include <ISceneManager.h>
#include <ICameraSceneNode.h>
#include <IMaterialRendererServices.h>
#include <set>
#include <algorithm>
using namespace irr;
class CallBase: public video::IShaderConstantSetCallBack
{
public:
CallBase()
{
firstdone = 0;
}
virtual void OnSetMaterial(const video::SMaterial &material)
{
mat = material;
}
protected:
bool firstdone;
video::SMaterial mat;
};
//
class NormalMapProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
NormalMapProvider(bool withLightmap)
{
m_with_lightmap = withLightmap;
}
private:
bool m_with_lightmap;
};
//
class WaterShaderProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setSpeed(const float s1, const float s2)
{
m_water_shader_speed_1 = s1;
m_water_shader_speed_2 = s2;
}
WaterShaderProvider()
{
m_dx_1 = 0.0f;
m_dx_2 = 0.0f;
m_dy_1 = 0.0f;
m_dy_2 = 0.0f;
m_water_shader_speed_1 =
m_water_shader_speed_2 = 0.0f;
}
void setSunPosition(const core::vector3df &in)
{
m_sunpos = in;
m_sunpos.normalize();
}
void setSpeed(float speed) { m_speed = speed; }
void setHeight(float height) { m_height = height; }
void setLength(float length) { m_length = length; }
private:
core::vector3df m_sunpos;
float m_dx_1, m_dy_1, m_dx_2, m_dy_2;
float m_water_shader_speed_1;
float m_water_shader_speed_2;
float m_speed;
float m_height;
float m_length;
};
//
class GrassShaderProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
GrassShaderProvider()
{
m_amplitude =
m_speed = 0.0f;
}
void setSpeed(float speed)
{
m_speed = speed;
}
void setAmplitude(float amp)
{
m_amplitude = amp;
}
private:
float m_amplitude, m_speed;
};
//
class SplattingProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class BubbleEffectProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
BubbleEffectProvider()
{
}
// We hijack the material type param 2 of bubbles.
// It's time to start the fade, negative if fade out, positive if in.
// It'd be unused otherwise.
void onMadeVisible(scene::IMeshBuffer * const mb)
{
if (!contains(mb))
return;
video::SMaterial &mat = mb->getMaterial();
mat.MaterialTypeParam2 = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
}
void onHidden(scene::IMeshBuffer * const mb)
{
if (!contains(mb))
return;
video::SMaterial &mat = mb->getMaterial();
mat.MaterialTypeParam2 = irr_driver->getDevice()->getTimer()->getTime() / -1000.0f;
}
void isInitiallyHidden(scene::IMeshBuffer * const mb)
{
if (!contains(mb))
return;
video::SMaterial &mat = mb->getMaterial();
mat.MaterialTypeParam2 = irr_driver->getDevice()->getTimer()->getTime() / -1000.0f;
}
void removeBubble(const scene::IMeshBuffer * const mb)
{
m_bubbles.erase(mb);
}
void addBubble(scene::IMeshBuffer * const mb)
{
m_bubbles.insert(mb);
video::SMaterial &mat = mb->getMaterial();
mat.MaterialTypeParam2 = 1;
}
bool contains(const scene::IMeshBuffer * const mb) const
{
return m_bubbles.count(mb);
}
private:
std::set<const scene::IMeshBuffer *> m_bubbles;
};
//
class RainEffectProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class SnowEffectProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class MotionBlurProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setMaxHeight(u32 who, float height)
{
assert(who < MAX_PLAYER_COUNT);
m_maxheight[who] = height;
}
void setBoostTime(u32 who, float time)
{
assert(who < MAX_PLAYER_COUNT);
m_boost_time[who] = time;
}
void setCenter(u32 who, float X, float Y)
{
assert(who < MAX_PLAYER_COUNT);
m_center[who].X = X;
m_center[who].Y = Y;
}
void setDirection(u32 who, float X, float Y)
{
assert(who < MAX_PLAYER_COUNT);
m_direction[who].X = X;
m_direction[who].Y = Y;
}
void setCurrentCamera(u32 who)
{
m_current_camera = who;
}
private:
float m_maxheight[MAX_PLAYER_COUNT];
u32 m_current_camera;
float m_boost_time[MAX_PLAYER_COUNT];
core::vector2df m_center[MAX_PLAYER_COUNT];
core::vector2df m_direction[MAX_PLAYER_COUNT];
};
//
class GaussianBlurProvider: public CallBase
{
public:
GaussianBlurProvider()
{
m_pixel[0] = 1.0f / UserConfigParams::m_width;
m_pixel[1] = 1.0f / UserConfigParams::m_height;
}
void setResolution(float x, float y)
{
m_pixel[0] = 1.0f / x;
m_pixel[1] = 1.0f / y;
}
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
private:
float m_pixel[2];
};
//
class MipVizProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class ColorizeProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setColor(float r, float g, float b)
{
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
private:
float m_color[3];
};
//
class GlowProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setResolution(float x, float y)
{
m_res[0] = x;
m_res[1] = y;
}
private:
float m_res[2];
};
//
class ObjectPassProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class LightBlendProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class PointLightProvider: public CallBase
{
public:
PointLightProvider()
{
m_screen[0] = UserConfigParams::m_width;
m_screen[1] = UserConfigParams::m_height;
m_specular = 200;
}
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setColor(float r, float g, float b)
{
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
void setPosition(float x, float y, float z)
{
m_pos[0] = x;
m_pos[1] = y;
m_pos[2] = z;
}
void setRadius(float r)
{
m_radius = r;
}
void setSpecular(float s)
{
m_specular = s;
}
void updateIPVMatrix()
{
// Update the campos and IPV matrix, only once per frame since it's costly
const core::vector3df &campos =
irr_driver->getSceneManager()->getActiveCamera()->getAbsolutePosition();
m_campos[0] = campos.X;
m_campos[1] = campos.Y;
m_campos[2] = campos.Z;
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
m_invprojview = drv->getTransform(video::ETS_PROJECTION);
m_invprojview *= drv->getTransform(video::ETS_VIEW);
m_invprojview.makeInverse();
}
private:
core::matrix4 m_invprojview;
float m_campos[3];
float m_color[3];
float m_pos[3];
float m_screen[2];
float m_radius;
float m_specular;
};
//
class SunLightProvider: public CallBase
{
public:
SunLightProvider()
{
m_screen[0] = UserConfigParams::m_width;
m_screen[1] = UserConfigParams::m_height;
m_wind[0] = m_wind[1] = 0;
}
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setColor(float r, float g, float b)
{
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
void setPosition(float x, float y, float z)
{
m_pos[0] = x;
m_pos[1] = y;
m_pos[2] = z;
}
void updateIPVMatrix()
{
// Update the IPV matrix, only once per frame since it's costly
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
m_invprojview = drv->getTransform(video::ETS_PROJECTION);
m_invprojview *= drv->getTransform(video::ETS_VIEW);
m_invprojview.makeInverse();
}
void setShadowMatrix(const core::matrix4 &mat)
{
m_shadowmat = mat;
}
private:
core::matrix4 m_invprojview, m_shadowmat;
float m_color[3];
float m_pos[3];
float m_screen[2];
float m_wind[2];
};
//
class BloomProvider: public CallBase
{
public:
BloomProvider() { m_threshold = 0.75f; }
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setThreshold(const float f) { m_threshold = f; }
private:
float m_threshold;
};
//
class MLAAColor1Provider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class MLAABlend2Provider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class MLAANeigh3Provider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class SSAOProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class GodRayProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
// In texcoords
void setSunPosition(float x, float y) { m_sunpos[0] = x; m_sunpos[1] = y; }
private:
float m_sunpos[2];
};
//
class ShadowPassProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class ShadowImportanceProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void updateIPVMatrix()
{
// Update the IPV matrix, only once per frame since it's costly
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
const core::vector3df &campos =
irr_driver->getSceneManager()->getActiveCamera()->getAbsolutePosition();
m_campos[0] = campos.X;
m_campos[1] = campos.Y;
m_campos[2] = campos.Z;
m_invprojview = drv->getTransform(video::ETS_PROJECTION);
m_invprojview *= drv->getTransform(video::ETS_VIEW);
m_invprojview.makeInverse();
}
void setShadowMatrix(const core::matrix4 &mat)
{
m_shadowmat = mat;
}
private:
core::matrix4 m_invprojview, m_shadowmat;
float m_campos[3];
};
//
class CollapseProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setResolution(const float x, const float y)
{
m_pixel[0] = 1.0f / x;
m_pixel[1] = 1.0f / y;
m_multi[0] = m_multi[1] = 1;
if (x < 2 || y < 2)
{
u32 i;
for (i = 0; i < 2; i++)
{
// No increase for the other direction
if (m_pixel[i] > 0.9f) m_pixel[i] = m_multi[i] = 0;
}
std::swap(m_multi[0], m_multi[1]);
}
m_size = std::max(x, y);
}
private:
float m_pixel[2];
int m_size;
float m_multi[2];
};
//
class BloomPowerProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setPower(float power)
{
m_power = power / 10.0f;
}
private:
float m_power;
};
//
class MultiplyProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class ShadowGenProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class CausticsProvider: public CallBase
{
public:
CausticsProvider() { m_dir[0] = m_dir[1] = m_dir2[0] = m_dir2[1] = 0; }
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
private:
float m_dir[2], m_dir2[2];
};
//
class DisplaceProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
DisplaceProvider()
{
m_screen[0] = UserConfigParams::m_width;
m_screen[1] = UserConfigParams::m_height;
m_dir[0] = m_dir[1] = m_dir2[0] = m_dir2[1] = 0;
}
private:
float m_screen[2];
float m_dir[2], m_dir2[2];
};
//
class PPDisplaceProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class FogProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void updateIPVMatrix()
{
// Update the campos and IPV matrix, only once per frame since it's costly
const core::vector3df &campos =
irr_driver->getSceneManager()->getActiveCamera()->getAbsolutePosition();
m_campos[0] = campos.X;
m_campos[1] = campos.Y;
m_campos[2] = campos.Z;
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
m_invprojview = drv->getTransform(video::ETS_PROJECTION);
m_invprojview *= drv->getTransform(video::ETS_VIEW);
m_invprojview.makeInverse();
}
private:
core::matrix4 m_invprojview;
float m_campos[3];
};
#endif

View File

@ -19,11 +19,7 @@
#include "graphics/camera.hpp"
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define isnan _isnan
#else
# include <math.h>
#endif
#include <math.h>
#include "audio/music_manager.hpp"
#include "config/user_config.hpp"
@ -40,6 +36,7 @@
#include "tracks/track.hpp"
#include "utils/aligned_array.hpp"
#include "utils/constants.hpp"
#include "utils/vs.hpp"
#include "ICameraSceneNode.h"
#include "ISceneManager.h"

85
src/graphics/glow.cpp Normal file
View File

@ -0,0 +1,85 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Lauri Kasanen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/glow.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/material.hpp"
#include "graphics/rtts.hpp"
#include "graphics/shaders.hpp"
using namespace video;
using namespace scene;
using namespace core;
IMesh * GlowNode::sphere = NULL;
SMaterial GlowNode::mat;
aabbox3df GlowNode::box;
GlowNode::GlowNode(scene::ISceneManager* mgr, float radius): ISceneNode(mgr->getRootSceneNode(), mgr, -1)
{
if (!sphere)
{
mat.Lighting = false;
mat.MaterialType = irr_driver->getShader(ES_GLOW);
mat.setTexture(0, irr_driver->getRTT(RTT_QUARTER1));
mat.TextureLayer[0].TextureWrapU =
mat.TextureLayer[0].TextureWrapV = ETC_CLAMP_TO_EDGE;
mat.setFlag(EMF_TRILINEAR_FILTER, true);
mat.BlendOperation = EBO_ADD;
sphere = mgr->getGeometryCreator()->createSphereMesh(1, 4, 4);
box = sphere->getBoundingBox();
}
setScale(vector3df(radius));
}
GlowNode::~GlowNode()
{
}
void GlowNode::render()
{
IVideoDriver * const drv = irr_driver->getVideoDriver();
drv->setTransform(ETS_WORLD, AbsoluteTransformation);
drv->setMaterial(mat);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 0, ~0);
glEnable(GL_STENCIL_TEST);
drv->drawMeshBuffer(sphere->getMeshBuffer(0));
glDisable(GL_STENCIL_TEST);
}
void GlowNode::OnRegisterSceneNode()
{
if (IsVisible)
{
SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
}
ISceneNode::OnRegisterSceneNode();
}

53
src/graphics/glow.hpp Normal file
View File

@ -0,0 +1,53 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Lauri Kasanen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_GLOW_HPP
#define HEADER_GLOW_HPP
#include <ISceneNode.h>
#include <IMesh.h>
using namespace irr;
// The actual node
class GlowNode: public scene::ISceneNode
{
public:
GlowNode(scene::ISceneManager* mgr, float radius);
~GlowNode();
virtual void render();
virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return box;
}
virtual void OnRegisterSceneNode();
virtual u32 getMaterialCount() const { return 1; }
virtual video::SMaterial& getMaterial(u32 i) { return mat; }
private:
static video::SMaterial mat;
static core::aabbox3df box;
static scene::IMesh *sphere;
};
#endif

21
src/graphics/glwrap.hpp Normal file
View File

@ -0,0 +1,21 @@
#ifndef GLWRAP_HEADER_H
#define GLWRAP_HEADER_H
#if defined(__APPLE__)
# include <OpenGL/gl.h>
#elif defined(ANDROID)
# include <GLES/gl.h>
#elif defined(WIN32)
# define _WINSOCKAPI_
// has to be included before gl.h because of WINGDIAPI and APIENTRY definitions
# include <windows.h>
# include <GL/gl.h>
#else
# include <GL/gl.h>
#endif
// already includes glext.h, which defines useful GL constants.
// COpenGLDriver has already loaded the extension GL functions we use (e.g glBeginQuery)
#include "../../lib/irrlicht/source/Irrlicht/COpenGLDriver.h"
#endif

View File

@ -19,13 +19,23 @@
#include "graphics/irr_driver.hpp"
#include "config/user_config.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/camera.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/hardware_skinning.hpp"
#include "graphics/lens_flare.hpp"
#include "graphics/light.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/per_camera_node.hpp"
#include "graphics/post_processing.hpp"
#include "graphics/referee.hpp"
#include "graphics/shaders.hpp"
#include "graphics/shadow_importance.hpp"
#include "graphics/sun.hpp"
#include "graphics/rtts.hpp"
#include "graphics/water.hpp"
#include "graphics/wind.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/modaldialog.hpp"
#include "guiengine/scalable_font.hpp"
@ -47,6 +57,7 @@
#include "utils/constants.hpp"
#include "utils/log.hpp"
#include "utils/profiler.hpp"
#include "utils/vs.hpp"
#include <irrlicht.h>
@ -62,19 +73,12 @@
using namespace irr;
#ifndef round
# define round(x) (floor(x+0.5f))
#endif
#ifdef WIN32
#include <Windows.h>
#endif
#if defined(__linux__) && !defined(ANDROID)
namespace X11
{
#include <X11/Xlib.h>
#include <X11/Xutil.h>
}
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
/** singleton */
@ -96,6 +100,11 @@ IrrDriver::IrrDriver()
m_resolution_changing = RES_CHANGE_NONE;
m_device = createDevice(video::EDT_NULL);
m_request_screenshot = false;
m_shaders = NULL;
m_rtts = NULL;
m_wind = new Wind();
m_mipviz = m_wireframe = m_normals = m_ssaoviz = \
m_lightviz = m_shadowviz = m_distortviz = 0;
} // IrrDriver
// ----------------------------------------------------------------------------
@ -117,6 +126,9 @@ IrrDriver::~IrrDriver()
m_device->drop();
m_device = NULL;
m_modes.clear();
delete m_shaders;
delete m_wind;
} // ~IrrDriver
// ----------------------------------------------------------------------------
@ -124,7 +136,7 @@ IrrDriver::~IrrDriver()
*/
void IrrDriver::reset()
{
m_post_processing->reset();
if (m_glsl) m_post_processing->reset();
} // reset
// ----------------------------------------------------------------------------
@ -135,22 +147,22 @@ Returns the parent window of "window" (i.e. the ancestor of window
that is a direct child of the root, or window itself if it is a direct child).
If window is the root window, returns window.
*/
X11::Window get_toplevel_parent(X11::Display* display, X11::Window window)
Window get_toplevel_parent(Display* display, Window window)
{
X11::Window parent;
X11::Window root;
X11::Window * children;
Window parent;
Window root;
Window * children;
unsigned int num_children;
while (true)
{
if (0 == X11::XQueryTree(display, window, &root,
if (0 == XQueryTree(display, window, &root,
&parent, &children, &num_children))
{
Log::fatal("irr_driver", "XQueryTree error\n");
}
if (children) { //must test for null
X11::XFree(children);
XFree(children);
}
if (window == root || parent == root) {
return window;
@ -201,7 +213,6 @@ void IrrDriver::updateConfigIfRelevant()
Log::warn("irr_driver", "Could not retrieve window location\n");
}
#elif defined(__linux__) && !defined(ANDROID)
using namespace X11;
const video::SExposedVideoData& videoData =
m_device->getVideoDriver()->getExposedVideoData();
Display* display = (Display*)videoData.OpenGLLinux.X11Display;
@ -384,7 +395,8 @@ void IrrDriver::initDevice()
m_gui_env = m_device->getGUIEnvironment();
m_video_driver = m_device->getVideoDriver();
m_glsl = m_video_driver->queryFeature(video::EVDF_ARB_GLSL) &&
m_video_driver->queryFeature(video::EVDF_TEXTURE_NPOT);
m_video_driver->queryFeature(video::EVDF_TEXTURE_NPOT) &&
UserConfigParams::m_pixel_shaders;
// This remaps the window, so it has to be done before the clear to avoid flicker
m_device->setResizable(false);
@ -396,6 +408,44 @@ void IrrDriver::initDevice()
if (m_glsl)
{
Log::info("irr_driver", "GLSL supported.");
// Order matters, create RTTs as soon as possible, as they are the largest blocks.
m_rtts = new RTT();
m_shaders = new Shaders();
m_shadow_importance = new ShadowImportance();
m_mrt.clear();
m_mrt.reallocate(3);
m_mrt.push_back(m_rtts->getRTT(RTT_COLOR));
m_mrt.push_back(m_rtts->getRTT(RTT_NORMAL));
m_mrt.push_back(m_rtts->getRTT(RTT_DEPTH));
irr::video::COpenGLDriver* gl_driver = (irr::video::COpenGLDriver*)m_device->getVideoDriver();
gl_driver->extGlGenQueries(1, &m_lensflare_query);
scene::IMesh * const sphere = m_scene_manager->getGeometryCreator()->createSphereMesh(1, 16, 16);
m_sun_interposer = m_scene_manager->addMeshSceneNode(sphere);
m_sun_interposer->grab();
m_sun_interposer->setParent(NULL);
m_sun_interposer->setScale(core::vector3df(20));
m_sun_interposer->getMaterial(0).Lighting = false;
m_sun_interposer->getMaterial(0).ColorMask = video::ECP_NONE;
m_sun_interposer->getMaterial(0).ZWriteEnable = false;
m_sun_interposer->getMaterial(0).MaterialType = m_shaders->getShader(ES_PASSFAR);
sphere->drop();
m_lensflare = new scene::CLensFlareSceneNode(NULL, m_scene_manager, -1);
video::ITexture * const tex =
m_video_driver->getTexture((file_manager->getTextureDir() + "lensflare.png").c_str());
if (!tex) Log::fatal("irr_driver", "Cannot find lens flare texture");
m_lensflare->setMaterialTexture(0, tex);
m_lensflare->setAutomaticCulling(scene::EAC_OFF);
m_suncam = m_scene_manager->addCameraSceneNode(0, vector3df(0), vector3df(0), -1, false);
m_suncam->grab();
m_suncam->setParent(NULL);
}
else
{
@ -407,7 +457,6 @@ void IrrDriver::initDevice()
{
#if defined(__linux__) && !defined(ANDROID)
// Set class hints on Linux, used by Window Managers.
using namespace X11;
const video::SExposedVideoData& videoData = m_video_driver
->getExposedVideoData();
XClassHint* classhint = XAllocClassHint();
@ -423,11 +472,6 @@ void IrrDriver::initDevice()
->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
m_device->getVideoDriver()
->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_QUALITY, true);
if (!UserConfigParams::m_fbo)
{
m_device->getVideoDriver()
->disableFeature(video::EVDF_FRAMEBUFFER_OBJECT);
}
// Force creation of mipmaps even if the mipmaps flag in a b3d file
// does not set the 'enable mipmap' flag.
@ -526,7 +570,6 @@ bool IrrDriver::moveWindow(const int x, const int y)
return false;
}
#elif defined(__linux__) && !defined(ANDROID)
using namespace X11;
const video::SExposedVideoData& videoData = m_video_driver->getExposedVideoData();
// TODO: Actually handle possible failure
XMoveWindow((Display*)videoData.OpenGLLinux.X11Display,
@ -771,6 +814,7 @@ void IrrDriver::setAllMaterialFlags(scene::IMesh *mesh) const
* \param wave_length Lenght of a water wave.
*/
scene::ISceneNode* IrrDriver::addWaterNode(scene::IMesh *mesh,
scene::IMesh **welded,
float wave_height,
float wave_speed,
float wave_length)
@ -778,11 +822,24 @@ scene::ISceneNode* IrrDriver::addWaterNode(scene::IMesh *mesh,
mesh->setMaterialFlag(video::EMF_GOURAUD_SHADING, true);
scene::IMesh* welded_mesh = m_scene_manager->getMeshManipulator()
->createMeshWelded(mesh);
scene::ISceneNode* out = m_scene_manager->addWaterSurfaceSceneNode(welded_mesh,
scene::ISceneNode* out = NULL;
if (!m_glsl)
{
out = m_scene_manager->addWaterSurfaceSceneNode(welded_mesh,
wave_height, wave_speed,
wave_length);
} else
{
out = new WaterNode(m_scene_manager, welded_mesh, wave_height, wave_speed,
wave_length);
}
out->getMaterial(0).setFlag(video::EMF_GOURAUD_SHADING, true);
welded_mesh->drop(); // The scene node keeps a reference
*welded = welded_mesh;
return out;
} // addWaterNode
@ -841,11 +898,22 @@ PerCameraNode *IrrDriver::addPerCameraMesh(scene::IMesh* mesh,
scene::ICameraSceneNode* camera,
scene::ISceneNode *parent)
{
scene::ISceneNode *node = m_scene_manager->addMeshSceneNode(mesh);
return new PerCameraNode((parent ? parent
: m_scene_manager->getRootSceneNode()),
m_scene_manager, -1, camera, mesh);
m_scene_manager, -1, camera, node);
} // addMesh
PerCameraNode *IrrDriver::addPerCameraNode(scene::ISceneNode* node,
scene::ICameraSceneNode* camera,
scene::ISceneNode *parent)
{
return new PerCameraNode((parent ? parent
: m_scene_manager->getRootSceneNode()),
m_scene_manager, -1, camera, node);
} // addNode
// ----------------------------------------------------------------------------
/** Adds a billboard node to scene.
@ -1627,6 +1695,8 @@ void IrrDriver::update(float dt)
m_resolution_changing = RES_CHANGE_NONE;
}
m_wind->update();
World *world = World::getWorld();
// Handle cut scenes (which do not have any karts in it)
@ -1651,97 +1721,24 @@ void IrrDriver::update(float dt)
m_video_driver->endScene();
return;
}
const bool inRace = world!=NULL;
if (inRace)
else if (!world)
{
// Start the RTT for post-processing.
// We do this before beginScene() because we want to capture the glClear()
// because of tracks that do not have skyboxes (generally add-on tracks)
m_post_processing->beginCapture();
}
m_video_driver->beginScene(/*backBuffer clear*/ true, /*zBuffer*/ true,
world ? world->getClearColor()
: video::SColor(255,100,101,140));
video::SColor(255,100,101,140));
if (inRace)
{
irr_driver->getVideoDriver()->enableMaterial2D();
RaceGUIBase *rg = world->getRaceGUI();
if (rg) rg->update(dt);
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera *camera = Camera::getCamera(i);
#ifdef ENABLE_PROFILER
std::ostringstream oss;
oss << "drawAll() for kart " << i << std::flush;
PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (i+1)*60,
0x00, 0x00);
#endif
camera->activate();
rg->preRenderCallback(camera); // adjusts start referee
m_scene_manager->drawAll();
PROFILER_POP_CPU_MARKER();
// Note that drawAll must be called before rendering
// the bullet debug view, since otherwise the camera
// is not set up properly. This is only used for
// the bullet debug view.
if (UserConfigParams::m_artist_debug_mode)
World::getWorld()->getPhysics()->draw();
} // for i<world->getNumKarts()
// Stop capturing for the post-processing
m_post_processing->endCapture();
// Render the post-processed scene
m_post_processing->render();
// Set the viewport back to the full screen for race gui
m_video_driver->setViewPort(core::recti(0, 0,
UserConfigParams::m_width,
UserConfigParams::m_height));
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera *camera = Camera::getCamera(i);
char marker_name[100];
sprintf(marker_name, "renderPlayerView() for kart %d", i);
PROFILER_PUSH_CPU_MARKER(marker_name, 0x00, 0x00, (i+1)*60);
rg->renderPlayerView(camera, dt);
PROFILER_POP_CPU_MARKER();
} // for i<getNumKarts
}
// Either render the gui, or the global elements of the race gui.
GUIEngine::render(dt);
// Render the profiler
if(UserConfigParams::m_profiler_enabled)
{
PROFILER_DRAW();
m_video_driver->endScene();
return;
}
#ifdef DEBUG
drawDebugMeshes();
#endif
m_video_driver->endScene();
if (m_glsl)
renderGLSL(dt);
else
renderFixed(dt);
if (m_request_screenshot) doScreenShot();
getPostProcessing()->update(dt);
// Enable this next print statement to get render information printed
// E.g. number of triangles rendered, culled etc. The stats is only
// printed while the race is running and not while the in-game menu
@ -1775,7 +1772,7 @@ bool IrrDriver::OnEvent(const irr::SEvent &event)
// Ignore 'normal' messages
if (event.LogEvent.Level > 1)
{
printf("[IrrDriver Temp Logger] Level %d: %s\n",
Log::warn("[IrrDriver Temp Logger]", "Level %d: %s\n",
event.LogEvent.Level,event.LogEvent.Text);
}
return true;
@ -1791,7 +1788,7 @@ bool IrrDriver::OnEvent(const irr::SEvent &event)
bool IrrDriver::supportsSplatting()
{
return UserConfigParams::m_pixel_shaders && m_glsl;
return m_glsl;
}
// ----------------------------------------------------------------------------
@ -1977,6 +1974,11 @@ video::ITexture* IrrDriver::RTTProvider::renderToTexture(float angle,
if (angle != -1 && m_rtt_main_node != NULL)
m_rtt_main_node->setRotation( core::vector3df(0, angle, 0) );
video::SOverrideMaterial &overridemat = m_video_driver->getOverrideMaterial();
overridemat.EnablePasses = scene::ESNRP_SOLID;
overridemat.EnableFlags = video::EMF_MATERIAL_TYPE;
overridemat.Material.MaterialType = video::EMT_SOLID;
if (m_rtt_main_node == NULL)
{
irr_driver->getSceneManager()->drawAll();
@ -1990,6 +1992,129 @@ video::ITexture* IrrDriver::RTTProvider::renderToTexture(float angle,
m_light->setVisible(false);
}
overridemat.EnablePasses = 0;
m_video_driver->setRenderTarget(0, false, false);
return m_render_target_texture;
}
void IrrDriver::applyObjectPassShader(scene::ISceneNode * const node, bool rimlit)
{
if (!m_glsl)
return;
// Don't override sky
if (node->getType() == scene::ESNT_SKY_DOME ||
node->getType() == scene::ESNT_SKY_BOX)
return;
const u32 mcount = node->getMaterialCount();
u32 i;
const video::E_MATERIAL_TYPE ref = rimlit ? m_shaders->getShader(ES_OBJECTPASS_RIMLIT):
m_shaders->getShader(ES_OBJECTPASS_REF);
const video::E_MATERIAL_TYPE pass = rimlit ? m_shaders->getShader(ES_OBJECTPASS_RIMLIT):
m_shaders->getShader(ES_OBJECTPASS);
const video::E_MATERIAL_TYPE origref = m_shaders->getShader(ES_OBJECTPASS_REF);
const video::E_MATERIAL_TYPE origpass = m_shaders->getShader(ES_OBJECTPASS);
bool viamb = false;
scene::IMesh *mesh = NULL;
if (node->getType() == scene::ESNT_ANIMATED_MESH)
{
viamb = ((scene::IAnimatedMeshSceneNode *) node)->isReadOnlyMaterials();
mesh = ((scene::IAnimatedMeshSceneNode *) node)->getMesh();
}
else if (node->getType() == scene::ESNT_MESH)
{
viamb = ((scene::IMeshSceneNode *) node)->isReadOnlyMaterials();
mesh = ((scene::IMeshSceneNode *) node)->getMesh();
}
for (i = 0; i < mcount; i++)
{
video::SMaterial &nodemat = node->getMaterial(i);
video::SMaterial &mbmat = mesh ? mesh->getMeshBuffer(i)->getMaterial() : nodemat;
video::SMaterial *mat = &nodemat;
if (viamb)
mat = &mbmat;
if (mat->MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF ||
mat->MaterialType == origref)
mat->MaterialType = ref;
else if (mat->MaterialType == video::EMT_SOLID ||
mat->MaterialType == origpass ||
(mat->MaterialType >= video::EMT_LIGHTMAP &&
mat->MaterialType <= video::EMT_LIGHTMAP_LIGHTING_M4))
mat->MaterialType = pass;
}
core::list<scene::ISceneNode*> kids = node->getChildren();
scene::ISceneNodeList::Iterator it = kids.begin();
for (; it != kids.end(); ++it)
{
applyObjectPassShader(*it, rimlit);
}
}
void IrrDriver::applyObjectPassShader()
{
if (!m_glsl)
return;
applyObjectPassShader(m_scene_manager->getRootSceneNode());
}
scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos, float radius,
float r, float g, float b, bool sun)
{
if (m_glsl)
{
LightNode *light = NULL;
if (!sun)
light = new LightNode(m_scene_manager, radius, r, g, b);
else
light = new SunNode(m_scene_manager, r, g, b);
light->grab();
light->setParent(NULL);
light->setPosition(pos);
light->updateAbsolutePosition();
m_lights.push_back(light);
if (sun) {
m_sun_interposer->setPosition(pos);
m_sun_interposer->updateAbsolutePosition();
m_lensflare->setPosition(pos);
m_lensflare->updateAbsolutePosition();
m_suncam->setPosition(pos);
m_suncam->updateAbsolutePosition();
((WaterShaderProvider *) m_shaders->m_callbacks[ES_WATER])->setSunPosition(pos);
}
return light;
} else
{
return m_scene_manager->addLightSceneNode(NULL, pos, video::SColorf(r, g, b), radius);
}
}
void IrrDriver::clearLights()
{
u32 i;
const u32 max = m_lights.size();
for (i = 0; i < max; i++)
{
m_lights[i]->drop();
}
m_lights.clear();
}

View File

@ -39,11 +39,15 @@
namespace irr
{
namespace scene { class ISceneManager; class IMesh; class IAnimatedMeshSceneNode; class IAnimatedMesh;
class IMeshSceneNode; class IParticleSystemSceneNode; class ICameraSceneNode; class ILightSceneNode; }
class IMeshSceneNode; class IParticleSystemSceneNode; class ICameraSceneNode; class ILightSceneNode;
class CLensFlareSceneNode; }
namespace gui { class IGUIEnvironment; class IGUIFont; }
}
using namespace irr;
#include "graphics/rtts.hpp"
#include "graphics/shaders.hpp"
#include "graphics/wind.hpp"
#include "utils/aligned_array.hpp"
#include "utils/no_copy.hpp"
#include "utils/ptr_vector.hpp"
@ -53,6 +57,8 @@ class AbstractKart;
class Camera;
class PerCameraNode;
class PostProcessing;
class LightNode;
class ShadowImportance;
/**
* \brief class that creates the irrLicht device and offers higher-level
@ -74,11 +80,22 @@ private:
gui::IGUIFont *m_race_font;
/** Post-processing. */
PostProcessing *m_post_processing;
/** Shaders. */
Shaders *m_shaders;
/** Wind. */
Wind *m_wind;
/** RTTs. */
RTT *m_rtts;
/** Shadow importance. */
ShadowImportance *m_shadow_importance;
/** Additional details to be shown in case that a texture is not found.
* This is used to specify details like: "while loading kart '...'" */
std::string m_texture_error_message;
/** The main MRT setup. */
core::array<video::IRenderTarget> m_mrt;
/** Flag to indicate if a resolution change is pending (which will be
* acted upon in the next update). None means no change, yes means
* change to new resolution and trigger confirmation dialog.
@ -99,6 +116,12 @@ public:
int getWidth() const {return m_width; }
int getHeight() const {return m_height; }
}; // VideoMode
struct BloomData {
scene::ISceneNode * node;
float power;
};
private:
std::vector<VideoMode> m_modes;
@ -116,6 +139,34 @@ private:
bool m_request_screenshot;
bool m_wireframe;
bool m_mipviz;
bool m_normals;
bool m_ssaoviz;
bool m_shadowviz;
bool m_lightviz;
bool m_distortviz;
u32 m_renderpass;
u32 m_lensflare_query;
scene::IMeshSceneNode *m_sun_interposer;
scene::CLensFlareSceneNode *m_lensflare;
scene::ICameraSceneNode *m_suncam;
struct GlowData {
scene::ISceneNode * node;
float r, g, b;
};
std::vector<GlowData> m_glowing;
std::vector<LightNode *> m_lights;
std::vector<BloomData> m_forcedbloom;
std::vector<scene::ISceneNode *> m_displacing;
std::vector<scene::ISceneNode *> m_background;
#ifdef DEBUG
/** Used to visualise skeletons. */
std::vector<irr::scene::IAnimatedMeshSceneNode*> m_debug_meshes;
@ -126,6 +177,9 @@ private:
irr::scene::ISkinnedMesh* mesh, int id);
#endif
void renderFixed(float dt);
void renderGLSL(float dt);
void doScreenShot();
public:
IrrDriver();
@ -151,7 +205,8 @@ public:
bool create_one_quad=false);
scene::IMesh *createTexturedQuadMesh(const video::SMaterial *material,
const double w, const double h);
scene::ISceneNode *addWaterNode(scene::IMesh *mesh, float wave_height,
scene::ISceneNode *addWaterNode(scene::IMesh *mesh, scene::IMesh **welded,
float wave_height,
float wave_speed, float wave_length);
scene::IMeshSceneNode*addOctTree(scene::IMesh *mesh);
scene::IMeshSceneNode*addSphere(float radius,
@ -161,6 +216,9 @@ public:
PerCameraNode *addPerCameraMesh(scene::IMesh* mesh,
scene::ICameraSceneNode* node,
scene::ISceneNode *parent = NULL);
PerCameraNode *addPerCameraNode(scene::ISceneNode* node,
scene::ICameraSceneNode* cam,
scene::ISceneNode *parent = NULL);
scene::ISceneNode *addBillboard(const core::dimension2d< f32 > size,
video::ITexture *texture,
scene::ISceneNode* parent=NULL, bool alphaTesting = false);
@ -286,9 +344,86 @@ public:
/** Returns a pointer to the post processing object. */
inline PostProcessing* getPostProcessing() {return m_post_processing;}
// ------------------------------------------------------------------------
inline core::vector3df getWind() {return m_wind->getWind();}
// ------------------------------------------------------------------------
inline video::E_MATERIAL_TYPE getShader(const ShaderType num) {return m_shaders->getShader(num);}
// ------------------------------------------------------------------------
inline video::IShaderConstantSetCallBack* getCallback(const ShaderType num) {return m_shaders->m_callbacks[num];}
// ------------------------------------------------------------------------
inline video::ITexture* getRTT(TypeRTT which) {return m_rtts->getRTT(which);}
// ------------------------------------------------------------------------
inline bool isGLSL() const { return m_glsl; }
// ------------------------------------------------------------------------
void toggleWireframe() { m_wireframe ^= 1; }
// ------------------------------------------------------------------------
void toggleMipVisualization() { m_mipviz ^= 1; }
// ------------------------------------------------------------------------
void toggleNormals() { m_normals ^= 1; }
// ------------------------------------------------------------------------
bool getNormals() { return m_normals; }
// ------------------------------------------------------------------------
void toggleSSAOViz() { m_ssaoviz ^= 1; }
// ------------------------------------------------------------------------
void toggleLightViz() { m_lightviz ^= 1; }
// ------------------------------------------------------------------------
bool getSSAOViz() { return m_ssaoviz; }
// ------------------------------------------------------------------------
void toggleShadowViz() { m_shadowviz ^= 1; }
// ------------------------------------------------------------------------
bool getShadowViz() { return m_shadowviz; }
// ------------------------------------------------------------------------
void toggleDistortViz() { m_distortviz ^= 1; }
// ------------------------------------------------------------------------
bool getDistortViz() { return m_distortviz; }
// ------------------------------------------------------------------------
u32 getRenderPass() { return m_renderpass; }
// ------------------------------------------------------------------------
void addGlowingNode(scene::ISceneNode *n, float r = 1.0f, float g = 1.0f, float b = 1.0f)
{
GlowData dat;
dat.node = n;
dat.r = r;
dat.g = g;
dat.b = b;
m_glowing.push_back(dat);
}
// ------------------------------------------------------------------------
void clearGlowingNodes() { m_glowing.clear(); }
// ------------------------------------------------------------------------
void addForcedBloomNode(scene::ISceneNode *n, float power = 1)
{
BloomData dat;
dat.node = n;
dat.power = power;
m_forcedbloom.push_back(dat);
}
// ------------------------------------------------------------------------
void clearForcedBloom() { m_forcedbloom.clear(); }
// ------------------------------------------------------------------------
const std::vector<BloomData> &getForcedBloom() const { return m_forcedbloom; }
// ------------------------------------------------------------------------
void clearDisplacingNodes() { m_displacing.clear(); }
// ------------------------------------------------------------------------
const std::vector<scene::ISceneNode *> &getDisplacingNodes() const { return m_displacing; }
// ------------------------------------------------------------------------
void addDisplacingNode(scene::ISceneNode * const n) { m_displacing.push_back(n); }
// ------------------------------------------------------------------------
void clearBackgroundNodes() { m_background.clear(); }
// ------------------------------------------------------------------------
void addBackgroundNode(scene::ISceneNode * const n) { m_background.push_back(n); }
// ------------------------------------------------------------------------
void applyObjectPassShader();
void applyObjectPassShader(scene::ISceneNode * const node, bool rimlit = false);
// ------------------------------------------------------------------------
scene::ISceneNode *addLight(const core::vector3df &pos, float radius = 1.0f, float r = 1.0f,
float g = 1.0f, float b = 1.0f, bool sun = false);
// ------------------------------------------------------------------------
void clearLights();
// ------------------------------------------------------------------------
scene::IMeshSceneNode *getSunInterposer() { return m_sun_interposer; }
#ifdef DEBUG
/** Removes debug meshes. */
void clearDebugMesh() { m_debug_meshes.clear(); }

View File

@ -0,0 +1,58 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __LARGE_MESH_BUFFER_H_INCLUDED__
#define __LARGE_MESH_BUFFER_H_INCLUDED__
#include "irrArray.h"
#include "IMeshBuffer.h"
#include "CMeshBuffer.h"
namespace irr
{
namespace scene
{
//! A SMeshBuffer with 32-bit indices
class LargeMeshBuffer : public SMeshBuffer
{
public:
//! Get type of index data which is stored in this meshbuffer.
/** \return Index type of this buffer. */
virtual video::E_INDEX_TYPE getIndexType() const
{
return video::EIT_32BIT;
}
//! Get pointer to indices
/** \return Pointer to indices. */
virtual const u16* getIndices() const
{
return (u16 *) Indices.const_pointer();
}
//! Get pointer to indices
/** \return Pointer to indices. */
virtual u16* getIndices()
{
return (u16 *) Indices.pointer();
}
//! Get number of indices
/** \return Number of indices. */
virtual u32 getIndexCount() const
{
return Indices.size();
}
//! Indices into the vertices of this buffer.
core::array<u32> Indices;
};
} // end namespace scene
} // end namespace irr
#endif

264
src/graphics/lens_flare.cpp Normal file
View File

@ -0,0 +1,264 @@
/* TODO: copyright */
#include "graphics/lens_flare.hpp"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "ISceneCollisionManager.h"
namespace irr
{
namespace scene
{
CLensFlareSceneNode::CLensFlareSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) :
scene::ISceneNode(parent, mgr, id)
{
#ifdef _DEBUG
setDebugName("CLensFlareSceneNode");
#endif
// set the bounding box
BBox.MaxEdge.set(0,0,0);
BBox.MinEdge.set(0,0,0);
// set the initial Strength
Strength = 1.0f;
// setup the vertices
Vertices[0] = video::S3DVertex(-1.f, -1.f, 0.f, 0.f, 0.f, 1.f, 0xffffffff, 0.f, 1.f);
Vertices[1] = video::S3DVertex(-1.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0xffffffff, 0.f, 0.f);
Vertices[2] = video::S3DVertex( 1.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0xffffffff, 1.f, 0.f);
Vertices[3] = video::S3DVertex( 1.f, -1.f, 0.f, 0.f, 0.f, 1.f, 0xffffffff, 1.f, 1.f);
// setup the indices
Indices[0] = 0;
Indices[1] = 1;
Indices[2] = 2;
Indices[3] = 2;
Indices[4] = 3;
Indices[5] = 0;
// set the default material properties
Material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
Material.Lighting = false;
Material.ZBuffer = video::ECFN_NEVER;
FlareData.reallocate(30);
// prepare the flare data array
// circles, halos and ring behind the sun
FlareData.push_back(SFlareData(EFT_CIRCLE, 0.5f, 0.12f, video::SColor(120, 60, 180, 35)));
FlareData.push_back(SFlareData(EFT_HALO, 0.45f, 0.4f, video::SColor(200, 100, 200, 60)));
FlareData.push_back(SFlareData(EFT_CIRCLE, 0.4f, 0.17f, video::SColor(240, 120, 220, 40)));
FlareData.push_back(SFlareData(EFT_CIRCLE, 0.2f, 0.35f, video::SColor(175, 175, 255, 20)));
FlareData.push_back(SFlareData(EFT_RING, 0.15f, 0.2f, video::SColor(120, 60, 255, 100)));
// sun and glow effect at sun position
FlareData.push_back(SFlareData(EFT_SUN, 0.0f, 0.75f, video::SColor(255, 255, 255, 255)));
// FlareData.push_back(SFlareData(EFT_STREAKS, 0.0f, 2.9f, video::SColor(255, 255, 255, 255)));
FlareData.push_back(SFlareData(EFT_GLOW, 0.0f, 3.5f, video::SColor(255, 255, 255, 255)));
// FlareData.push_back(SFlareData(EFT_RING, 0.0f, 1.5f, video::SColor(120, 120, 120, 150)));
// some lenses, halos and circles
FlareData.push_back(SFlareData(EFT_LENS, -0.15f, 0.15f, video::SColor(255, 60, 60, 90)));
FlareData.push_back(SFlareData(EFT_HALO, -0.3f, 0.3f, video::SColor(120, 60, 255, 180)));
FlareData.push_back(SFlareData(EFT_HALO, -0.4f, 0.2f, video::SColor(220, 80, 80, 98)));
FlareData.push_back(SFlareData(EFT_CIRCLE, -0.45f, 0.1f, video::SColor(220, 80, 80, 85)));
FlareData.push_back(SFlareData(EFT_RING, -0.42f, 0.3f, video::SColor(180, 60, 255, 110)));
// some small lenses, halos and rings
FlareData.push_back(SFlareData(EFT_LENS, -0.55f, 0.2f, video::SColor(255, 60, 60, 130)));
FlareData.push_back(SFlareData(EFT_HALO, -0.6f, 0.3f, video::SColor(120, 60, 255, 80)));
FlareData.push_back(SFlareData(EFT_LENS, -0.7f, 0.2f, video::SColor(200, 60, 60, 130)));
FlareData.push_back(SFlareData(EFT_LENS, -0.71f, 0.2f, video::SColor(200, 60, 130, 60)));
FlareData.push_back(SFlareData(EFT_LENS, -0.72f, 0.2f, video::SColor(200, 130, 130, 60)));
FlareData.push_back(SFlareData(EFT_LENS, -0.74f, 0.2f, video::SColor(200, 130, 60, 60)));
// some polyons, lenses and circle
FlareData.push_back(SFlareData(scene::EFT_POLY, -0.79f, 0.2f, video::SColor(200, 60, 130, 60)));
FlareData.push_back(SFlareData(scene::EFT_POLY, -0.86f, 0.3f, video::SColor(200, 130, 130, 60)));
FlareData.push_back(SFlareData(scene::EFT_LENS, -0.87f, 0.3f, video::SColor(180,255,192,178)));
FlareData.push_back(SFlareData(scene::EFT_CIRCLE, -0.9f, 0.1f, video::SColor(200, 60, 60, 130)));
FlareData.push_back(SFlareData(scene::EFT_POLY, -0.93f, 0.4f, video::SColor(200, 130, 60, 60)));
// finally som polygons
FlareData.push_back(SFlareData(EFT_POLY, -0.95f, 0.6f, video::SColor(120, 60, 255, 120)));
FlareData.push_back(SFlareData(EFT_POLY, -1.0f, 0.15f, video::SColor(120, 20, 255, 85)));
}
CLensFlareSceneNode::~CLensFlareSceneNode()
{
}
u32 CLensFlareSceneNode::getMaterialCount() const
{
// return the material count (always one in our case)
return 1;
}
video::SMaterial& CLensFlareSceneNode::getMaterial(u32 i)
{
// return the material
return Material;
}
core::array<SFlareData>& CLensFlareSceneNode::getFlareData()
{
// return the flare data array
return FlareData;
}
void CLensFlareSceneNode::OnRegisterSceneNode()
{
// if node is visible and Strength is greater than 0 register it for the ESNRP_TRANSPARENT_EFFECT pass
if(IsVisible && Strength > 0.0f)
{
SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT_EFFECT);
}
// call base OnRegisterSceneNode
ISceneNode::OnRegisterSceneNode();
}
void CLensFlareSceneNode::render()
{
// get the videodriver and the active camera
video::IVideoDriver* driver = SceneManager->getVideoDriver();
ICameraSceneNode* camera = SceneManager->getActiveCamera();
// return if we don't have a valid driver or a valid camera
// or if we have no texture attached to the material
if (!camera || !driver || !Material.getTexture(0))
return;
// get screencenter
const core::vector2d<s32> screenCenter = core::vector2d<s32>(
SceneManager->getVideoDriver()->getScreenSize().Width,
SceneManager->getVideoDriver()->getScreenSize().Height)/2;
// get screencoordinates of the node
const core::vector2d<s32> lightPos = SceneManager->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(
getAbsolutePosition(),
camera);
// store old projection matrix
core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
// store old view matrix
core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
// clear the projection matrix
driver->setTransform(video::ETS_PROJECTION, core::IdentityMatrix);
// clear the view matrix
driver->setTransform(video::ETS_VIEW, core::IdentityMatrix);
// set the transform
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
// set the material
driver->setMaterial(Material);
// calculate some handy constants
const f32 texPos = 1.0f/EFT_COUNT;
const s32 texHeight = s32(Material.getTexture(0)->getSize().Height*0.5f);
const f32 screenWidth = f32(driver->getScreenSize().Width);
const f32 screenHeight = f32(driver->getScreenSize().Height);
// render the flares
for (u32 i=0; i<FlareData.size(); ++i)
{
// get the flare element
SFlareData& flare = FlareData[i];
// calculate center of the flare
core::vector2d<s32>flarePos = screenCenter.getInterpolated(lightPos, -2.0*flare.Position);
// calculate flareposition in vertex coordinates using the scalefactor of the flare
s32 flareScale = s32((texHeight*flare.Scale));
core::rect<f32> flareRect = core::rect<f32>(
-1.f + 2.f * f32(flarePos.X-flareScale) / screenWidth,
-1.f + 2.f * f32(screenHeight-flarePos.Y-flareScale) / screenHeight,
-1.f + 2.f * f32(flarePos.X+flareScale) / screenWidth,
-1.f + 2.f * f32(screenHeight-flarePos.Y+flareScale) / screenHeight);
// calculate flarecolor in dependence of occlusion
f32 flareAlpha = f32(flare.Color.getAlpha()) / 255.f;
video::SColor flareColor(255,
(u32)(Strength * flareAlpha * flare.Color.getRed()),
(u32)(Strength * flareAlpha * flare.Color.getGreen()),
(u32)(Strength * flareAlpha * flare.Color.getBlue()));
// set vertex colors
Vertices[0].Color = flareColor;
Vertices[1].Color = flareColor;
Vertices[2].Color = flareColor;
Vertices[3].Color = flareColor;
// set texture coordinates
Vertices[0].TCoords.set( flare.Type * texPos, 1.0f);
Vertices[1].TCoords.set( flare.Type * texPos, 0.0f);
Vertices[2].TCoords.set((flare.Type+1) * texPos, 0.0f);
Vertices[3].TCoords.set((flare.Type+1) * texPos, 1.0f);
// set vertex positions
Vertices[0].Pos.set(flareRect.UpperLeftCorner.X, flareRect.UpperLeftCorner.Y, 0);
Vertices[1].Pos.set(flareRect.UpperLeftCorner.X, flareRect.LowerRightCorner .Y, 0);
Vertices[2].Pos.set(flareRect.LowerRightCorner.X, flareRect.LowerRightCorner.Y, 0);
Vertices[3].Pos.set(flareRect.LowerRightCorner.X, flareRect.UpperLeftCorner.Y, 0);
//draw the mesh
driver->drawIndexedTriangleList(Vertices, 4, Indices, 2);
}
// restore view matrix
driver->setTransform(video::ETS_VIEW, oldViewMat);
// restore projection matrix
driver->setTransform(video::ETS_PROJECTION, oldProjMat);
}
const core::aabbox3df& CLensFlareSceneNode::getBoundingBox() const
{
// return the bounding box
return BBox;
}
ESCENE_NODE_TYPE CLensFlareSceneNode::getType() const
{
// return type of the scene node
// (important when using with a custom scene node factory)
return scene::ESNT_UNKNOWN; //(ESCENE_NODE_TYPE) ECSNT_LENSFLARE;
}
void CLensFlareSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
// write attributes of the scene node.
ISceneNode::serializeAttributes(out, options);
}
void CLensFlareSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
// read attributes of the scene node.
ISceneNode::deserializeAttributes(in, options);
}
ISceneNode* CLensFlareSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
CLensFlareSceneNode* nb = new CLensFlareSceneNode(newParent, newManager, ID);
nb->cloneMembers(this, newManager);
nb->Material = Material;
nb->drop();
return nb;
}
}// end irr namespace
}// end scene namespace

117
src/graphics/lens_flare.hpp Normal file
View File

@ -0,0 +1,117 @@
#ifndef _CLENSFLARESCENENODE_H
#define _CLENSFLARESCENENODE_H
#include <ISceneNode.h>
#include <S3DVertex.h>
namespace irr
{
namespace scene
{
// enum with different flare types (used by SFlareData)
enum E_FLARE_TYPE
{
EFT_SUN = 0,
EFT_GLOW,
EFT_LENS,
EFT_STREAKS,
EFT_RING,
EFT_HALO,
EFT_CIRCLE,
EFT_POLY,
EFT_COUNT
};
// struct holding the flare specification
struct SFlareData
{
public:
// constructor
SFlareData(const E_FLARE_TYPE type, const float position,
const float scale, const video::SColor &color)
{
Type = type;
Position = position;
Scale = scale;
Color = color;
}
// flare type
E_FLARE_TYPE Type;
// position
f32 Position;
// flare scale
f32 Scale;
// flare color
video::SColor Color;
};
class CLensFlareSceneNode : public ISceneNode
{
public:
// constructor
CLensFlareSceneNode(ISceneNode* parent, scene::ISceneManager* mgr, s32 id = -1);
// destructor
virtual ~CLensFlareSceneNode();
protected:
// material of the node
video::SMaterial Material;
// Bounding box
core::aabbox3d<f32> BBox;
// vertices and indices of a flare element
video::S3DVertex Vertices[4];
u16 Indices[6];
// flare data array
core::array<SFlareData> FlareData;
// Strength of the flare effect (between 0 and 1)
f32 Strength;
public:
// typical OnRegisterSceneNode function
virtual void OnRegisterSceneNode();
// renders the node
virtual void render();
// returns the bounding box
virtual const core::aabbox3d<f32>& getBoundingBox() const;
// returns the node type
virtual ESCENE_NODE_TYPE getType() const;
// returns the material count
virtual u32 getMaterialCount() const;
// returns the material
virtual video::SMaterial& getMaterial(u32 i);
// writes attributes of the scene node.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options = 0) const;
// reads attributes of the scene node.
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options = 0);
// clones the node
virtual ISceneNode* clone(ISceneNode* newParent = 0, ISceneManager* newManager = 0);
// returns the flare data array
core::array<SFlareData>& getFlareData();
// returns the strength (visibility) of the flares
f32 getStrength() { return Strength; }
// sets the strength (visibility) of the flares
void setStrength(f32 strength) { Strength = core::clamp(strength, 0.0f, 0.7f); }
};
} // end namespace scene
} // end namespace irr
#endif

93
src/graphics/light.cpp Normal file
View File

@ -0,0 +1,93 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Lauri Kasanen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/light.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/material.hpp"
#include "graphics/rtts.hpp"
#include "graphics/shaders.hpp"
using namespace video;
using namespace scene;
using namespace core;
IMesh * LightNode::sphere = NULL;
SMaterial LightNode::mat;
aabbox3df LightNode::box;
LightNode::LightNode(scene::ISceneManager* mgr, float radius, float r, float g, float b):
ISceneNode(mgr->getRootSceneNode(), mgr, -1)
{
if (!sphere)
{
mat.Lighting = false;
mat.MaterialType = irr_driver->getShader(ES_POINTLIGHT);
mat.setTexture(0, irr_driver->getRTT(RTT_NORMAL));
mat.setTexture(1, irr_driver->getRTT(RTT_DEPTH));
for (u32 i = 0; i < MATERIAL_MAX_TEXTURES; ++i)
{
mat.TextureLayer[i].TextureWrapU =
mat.TextureLayer[i].TextureWrapV = ETC_CLAMP_TO_EDGE;
}
mat.setFlag(EMF_BILINEAR_FILTER, false);
mat.setFlag(EMF_ZWRITE_ENABLE, false);
mat.MaterialTypeParam = pack_textureBlendFunc(EBF_ONE, EBF_ONE);
mat.BlendOperation = EBO_ADD;
sphere = mgr->getGeometryCreator()->createSphereMesh(1, 16, 16);
box = sphere->getBoundingBox();
}
setScale(vector3df(radius));
m_radius = radius;
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
LightNode::~LightNode()
{
}
void LightNode::render()
{
PointLightProvider * const cb = (PointLightProvider *) irr_driver->getCallback(ES_POINTLIGHT);
cb->setColor(m_color[0], m_color[1], m_color[2]);
cb->setPosition(getPosition().X, getPosition().Y, getPosition().Z);
cb->setRadius(m_radius);
IVideoDriver * const drv = irr_driver->getVideoDriver();
drv->setTransform(ETS_WORLD, AbsoluteTransformation);
drv->setMaterial(mat);
drv->drawMeshBuffer(sphere->getMeshBuffer(0));
}
void LightNode::OnRegisterSceneNode()
{ // This node is only drawn manually.
}

64
src/graphics/light.hpp Normal file
View File

@ -0,0 +1,64 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Lauri Kasanen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_LIGHT_HPP
#define HEADER_LIGHT_HPP
#include <ISceneNode.h>
#include <utils/cpp2011.h>
using namespace irr;
namespace irr
{
namespace scene { class IMesh; }
}
// The actual node
class LightNode: public scene::ISceneNode
{
public:
LightNode(scene::ISceneManager* mgr, float radius, float r, float g, float b);
virtual ~LightNode();
virtual void render() OVERRIDE;
virtual const core::aabbox3d<f32>& getBoundingBox() const OVERRIDE
{
return box;
}
virtual void OnRegisterSceneNode() OVERRIDE;
virtual u32 getMaterialCount() const OVERRIDE { return 1; }
virtual video::SMaterial& getMaterial(u32 i) OVERRIDE { return mat; }
float getRadius() const { return m_radius; }
void getColor(float out[3]) const { memcpy(out, m_color, 3 * sizeof(float)); }
protected:
static video::SMaterial mat;
static core::aabbox3df box;
static scene::IMesh *sphere;
float m_radius;
float m_color[3];
};
#endif

View File

@ -49,6 +49,7 @@ LODNode::LODNode(std::string group_name, scene::ISceneNode* parent,
drop();
m_forced_lod = -1;
m_last_tick = 0;
}
LODNode::~LODNode()
@ -81,6 +82,11 @@ int LODNode::getLevel()
if (dist < m_detail[n])
return n;
}
// If it's the shadow pass, and we would have otherwise hidden the item, show the min one
if (curr_cam->isOrthogonal())
return m_detail.size() - 1;
return -1;
} // getLevel
@ -139,9 +145,12 @@ void LODNode::OnRegisterSceneNode()
shown = true;
}
const u32 now = irr_driver->getDevice()->getTimer()->getTime();
// support an optional, mostly hard-coded fade-in/out effect for objects with a single level
if (m_nodes.size() == 1 && (m_nodes[0]->getType() == scene::ESNT_MESH ||
m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH))
m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH) &&
now > m_last_tick)
{
if (m_previous_visibility == WAS_HIDDEN && shown)
{
@ -237,6 +246,7 @@ void LODNode::OnRegisterSceneNode()
}
m_previous_visibility = (shown ? WAS_SHOWN : WAS_HIDDEN);
m_last_tick = now;
// If this node has children other than the LOD nodes, draw them
core::list<ISceneNode*>::Iterator it;
@ -279,7 +289,13 @@ void LODNode::add(int level, scene::ISceneNode* node, bool reparent)
if(UserConfigParams::m_hw_skinning_enabled && node->getType() == scene::ESNT_ANIMATED_MESH)
HardwareSkinning::prepareNode((scene::IAnimatedMeshSceneNode*)node);
if (node->getType() == scene::ESNT_ANIMATED_MESH)
((scene::IAnimatedMeshSceneNode *) node)->setReadOnlyMaterials(true);
if (node->getType() == scene::ESNT_MESH)
((scene::IMeshSceneNode *) node)->setReadOnlyMaterials(true);
node->drop();
node->updateAbsolutePosition();
irr_driver->applyObjectPassShader(node);
}

View File

@ -71,6 +71,8 @@ private:
PreviousVisibility m_previous_visibility;
u32 m_last_tick;
public:
LODNode(std::string group_name, scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id=-1);

View File

@ -27,8 +27,10 @@
#include "config/user_config.hpp"
#include "config/stk_config.hpp"
#include "guiengine/engine.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/shaders.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp"
@ -36,7 +38,6 @@
#include "tracks/track.hpp"
#include "utils/log.hpp"
#include <IGPUProgrammingServices.h>
#include <IMaterialRendererServices.h>
#include <ISceneNode.h>
#include <IShaderConstantSetCallBack.h>
@ -46,351 +47,6 @@ using namespace irr::video;
const unsigned int UCLAMP = 1;
const unsigned int VCLAMP = 2;
//-----------------------------------------------------------------------------
class NormalMapProvider : public video::IShaderConstantSetCallBack
{
bool m_with_lightmap;
public:
LEAK_CHECK()
NormalMapProvider(bool withLightmap)
{
m_with_lightmap = withLightmap;
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
s32 decaltex = 0;
services->setPixelShaderConstant("DecalTex", &decaltex, 1);
s32 bumptex = 1;
services->setPixelShaderConstant("BumpTex", &bumptex, 1);
s32 lightmapTex = (m_with_lightmap ? 2 : 0);
services->setPixelShaderConstant("LightMapTex", &lightmapTex, 1);
s32 hasLightMap = (m_with_lightmap ? 1 : 0);
services->setPixelShaderConstant("HasLightMap", &hasLightMap, 1);
// We could calculate light direction as coming from the sun (then we'd need to
// transform it into camera space). But I find that pretending light
// comes from the camera gives good results
const float lightdir[] = {0.1852f, -0.1852f, -0.9259f};
services->setVertexShaderConstant("lightdir", lightdir, 3);
}
};
//-----------------------------------------------------------------------------
class WaterShaderProvider : public video::IShaderConstantSetCallBack
{
float m_dx_1, m_dy_1, m_dx_2, m_dy_2;
float m_water_shader_speed_1;
float m_water_shader_speed_2;
bool m_fog;
public:
LEAK_CHECK()
void enableFog(bool enable)
{
m_fog = enable;
}
WaterShaderProvider(float water_shader_speed_1,
float water_shader_speed_2)
{
m_dx_1 = 0.0f;
m_dy_1 = 0.0f;
m_dx_2 = 0.0f;
m_dy_2 = 0.0f;
m_water_shader_speed_1 = water_shader_speed_1/100.0f;
m_water_shader_speed_2 = water_shader_speed_2/100.0f;
m_fog = false;
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
m_dx_1 += GUIEngine::getLatestDt()*m_water_shader_speed_1;
m_dy_1 += GUIEngine::getLatestDt()*m_water_shader_speed_1;
m_dx_2 += GUIEngine::getLatestDt()*m_water_shader_speed_2;
m_dy_2 -= GUIEngine::getLatestDt()*m_water_shader_speed_2;
if (m_dx_1 > 1.0f) m_dx_1 -= 1.0f;
if (m_dy_1 > 1.0f) m_dy_1 -= 1.0f;
if (m_dx_2 > 1.0f) m_dx_2 -= 1.0f;
if (m_dy_2 < 0.0f) m_dy_2 += 1.0f;
s32 decaltex = 0;
services->setPixelShaderConstant("DecalTex", &decaltex, 1);
s32 bumptex = 1;
services->setPixelShaderConstant("BumpTex1", &bumptex, 1);
bumptex = 2;
services->setPixelShaderConstant("BumpTex2", &bumptex, 1);
// We could calculate light direction as coming from the sun (then we'd need to
// transform it into camera space). But I find that pretending light
// comes from the camera gives good results
const float lightdir[] = {-0.315f, 0.91f, -0.3f};
services->setVertexShaderConstant("lightdir", lightdir, 3);
services->setVertexShaderConstant("delta1", &m_dx_1, 2);
services->setVertexShaderConstant("delta2", &m_dx_2, 2);
if (m_fog)
{
Track* t = World::getWorld()->getTrack();
float fogStart = t->getFogStart();
services->setPixelShaderConstant("fogFrom", &fogStart, 1);
float fogEnd = t->getFogEnd();
services->setPixelShaderConstant("fogTo", &fogEnd, 1);
video::SColor fogColor = t->getFogColor();
float fogColorVec[] = {fogColor.getRed()/255.0f,
fogColor.getGreen()/255.0f,
fogColor.getBlue()/255.0f, 1.0f};
services->setVertexShaderConstant("fogColor", fogColorVec, 4);
}
}
};
//-----------------------------------------------------------------------------
// FIXME: refactor this hack to get per-instance properties, and apply the
// clean fix to all shaders why we're at it......
std::map<int, float> grass_shaders_times;
int grass_shaders_times_index = 0;
class GrassShaderProvider : public video::IShaderConstantSetCallBack
{
bool m_fog;
float m_angle;
float m_amplitude;
float m_speed;
public:
LEAK_CHECK()
GrassShaderProvider(float amplitude, float speed)
{
m_fog = false;
m_angle = 0.0f;
m_amplitude = amplitude;
m_speed = speed;
}
void enableFog(bool enable)
{
m_fog = enable;
}
void update(float dt)
{
m_angle += GUIEngine::getLatestDt()*m_speed;
if (m_angle > M_PI*2) m_angle -= M_PI*2;
}
virtual void OnSetConstants(irr::video::IMaterialRendererServices *services,
s32 userData)
{
grass_shaders_times[userData] += GUIEngine::getLatestDt()*m_speed;
if (grass_shaders_times[userData] > M_PI*2) grass_shaders_times[userData] -= M_PI*2;
services->setVertexShaderConstant("angle", &grass_shaders_times[userData], 1);
int fog = (m_fog ? 1 : 0);
services->setVertexShaderConstant("fog", &fog, 1);
s32 tex = 0;
services->setVertexShaderConstant("tex", &tex, 1);
services->setVertexShaderConstant("amplitude", &m_amplitude, 1);
if (m_fog)
{
Track* t = World::getWorld()->getTrack();
float fogStart = t->getFogStart();
services->setPixelShaderConstant("fogFrom", &fogStart, 1);
float fogEnd = t->getFogEnd();
services->setPixelShaderConstant("fogTo", &fogEnd, 1);
video::SColor fogColor = t->getFogColor();
float fogColorVec[] = {fogColor.getRed()/255.0f,
fogColor.getGreen()/255.0f,
fogColor.getBlue()/255.0f, 1.0f};
services->setVertexShaderConstant("fogColor", fogColorVec, 4);
}
}
};
//-----------------------------------------------------------------------------
#if 0
#pragma mark -
#endif
class SplattingProvider : public video::IShaderConstantSetCallBack
{
core::vector3df m_light_direction;
bool m_light_dir_calculated;
bool m_lightmap;
public:
LEAK_CHECK()
SplattingProvider(bool lightmap)
{
m_light_dir_calculated = false;
m_lightmap = lightmap;
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
if (!m_light_dir_calculated)
{
m_light_dir_calculated = true;
m_light_direction = -World::getWorld()->getTrack()->getSunRotation().rotationToDirection();
}
s32 tex_layout = 1;
services->setPixelShaderConstant("tex_layout", &tex_layout, 1);
s32 tex_detail0 = 2;
services->setPixelShaderConstant("tex_detail0", &tex_detail0, 1);
s32 tex_detail1 = 3;
services->setPixelShaderConstant("tex_detail1", &tex_detail1, 1);
s32 tex_detail2 = 4;
services->setPixelShaderConstant("tex_detail2", &tex_detail2, 1);
s32 tex_detail3 = 5;
services->setPixelShaderConstant("tex_detail3", &tex_detail3, 1);
if (m_lightmap)
{
s32 tex_lightmap = 6;
services->setPixelShaderConstant("tex_lightmap", &tex_lightmap, 1);
}
services->setVertexShaderConstant("lightdir", &m_light_direction.X, 3);
}
};
//-----------------------------------------------------------------------------
#if 0
#pragma mark -
#endif
class SphereMapProvider: public video::IShaderConstantSetCallBack
{
core::vector3df m_light_direction;
public:
LEAK_CHECK()
SphereMapProvider()
{
m_light_direction = core::vector3df(-0.6f, -0.5f, -0.63f);
//m_light_direction = core::vector3df(-0.315f, 0.91f, -0.3f);
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
s32 texture = 0;
services->setPixelShaderConstant("texture", &texture, 1);
services->setVertexShaderConstant("lightdir", &m_light_direction.X, 3);
}
};
//-----------------------------------------------------------------------------
#if 0
#pragma mark -
#endif
class BubbleEffectProvider : public video::IShaderConstantSetCallBack
{
irr::u32 initial_time;
float m_transparency;
bool m_is_visible;
public:
LEAK_CHECK()
BubbleEffectProvider()
{
initial_time = irr_driver->getDevice()->getTimer()->getRealTime();
m_transparency = 1.0f;
m_is_visible = true;
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
if (m_is_visible && m_transparency < 1.0f)
{
m_transparency += GUIEngine::getLatestDt()*0.3f;
if (m_transparency > 1.0f) m_transparency = 1.0f;
}
else if (!m_is_visible && m_transparency > 0.0f)
{
m_transparency -= GUIEngine::getLatestDt()*0.3f;
if (m_transparency < 0.0f) m_transparency = 0.0f;
}
float time = (irr_driver->getDevice()->getTimer()->getRealTime() - initial_time) / 1000.0f;
services->setVertexShaderConstant("time", &time, 1);
services->setVertexShaderConstant("transparency", &m_transparency, 1);
}
void onMadeVisible()
{
m_is_visible = true;
}
void onHidden()
{
m_is_visible = false;
m_transparency = 0.0f;
}
void isInitiallyHidden()
{
m_is_visible = false;
m_transparency = 0.0f;
}
};
#if 0
#pragma mark -
#endif
//-----------------------------------------------------------------------------
/** Create a new material using the parameters specified in the xml file.
* \param node Node containing the parameters for this material.
@ -568,7 +224,10 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
node->get("splatting-texture-2", &m_splatting_texture_2);
node->get("splatting-texture-3", &m_splatting_texture_3);
node->get("splatting-texture-4", &m_splatting_texture_4);
node->get("splatting-lightmap", &m_splatting_lightmap);
}
else if (s == "caustics")
{
m_graphical_effect = GE_CAUSTICS;
}
else if (s == "none")
{
@ -740,8 +399,6 @@ void Material::init(unsigned int index)
m_water_splash = false;
m_is_jump_texture = false;
m_shaders.resize(SHADER_COUNT, NULL);
for (int n=0; n<EMIT_KINDS_COUNT; n++)
{
m_particles_effects[n] = NULL;
@ -800,20 +457,6 @@ Material::~Material()
irr_driver->removeTexture(m_texture);
}
for (unsigned int n=0; n<m_shaders.size(); n++)
{
if (m_shaders[n])
{
m_shaders[n]->drop();
}
}
for (std::map<scene::IMeshBuffer*, BubbleEffectProvider*>::iterator it = m_bubble_provider.begin();
it != m_bubble_provider.end(); it++)
{
it->second->drop();
}
// If a special sfx is installed (that isn't part of stk itself), the
// entry needs to be removed from the sfx_manager's mapping, since other
// tracks might use the same name.
@ -1032,23 +675,9 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
}
if (m_smooth_reflection_shader)
{
if (UserConfigParams::m_pixel_shaders &&
irr_driver->isGLSL())
if (irr_driver->isGLSL())
{
if (m_shaders[SHADER_SPHERE_MAP] == NULL)
{
m_shaders[SHADER_SPHERE_MAP] = new SphereMapProvider();
}
// Material and shaders
IGPUProgrammingServices* gpu =
irr_driver->getVideoDriver()->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + "spheremap.vert").c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + "spheremap.frag").c_str(),
"main", video::EPST_PS_2_0,
m_shaders[SHADER_SPHERE_MAP], video::EMT_SOLID_2_LAYER );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
m->MaterialType = irr_driver->getShader(ES_SPHERE_MAP);
}
else
{
@ -1067,6 +696,12 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
}
}
if (m_graphical_effect == GE_SPHERE_MAP)
{
if (irr_driver->isGLSL())
{
m->MaterialType = irr_driver->getShader(ES_SPHERE_MAP);
}
else
{
m->MaterialType = video::EMT_SPHERE_MAP;
@ -1081,7 +716,8 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
modes++;
}
}
#if !LIGHTMAP_VISUALISATION
}
if (m_lightmap)
{
m->MaterialType = video::EMT_LIGHTMAP;
@ -1092,7 +728,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
m->MaterialType = video::EMT_LIGHTMAP_ADD;
modes++;
}
#endif
if (m_add)
{
//m->MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
@ -1111,8 +747,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_graphical_effect == GE_NORMAL_MAP)
{
IVideoDriver* video_driver = irr_driver->getVideoDriver();
if (UserConfigParams::m_pixel_shaders &&
irr_driver->isGLSL())
if (irr_driver->isGLSL())
{
ITexture* tex = irr_driver->getTexture(m_normal_map_tex);
if (m_is_heightmap)
@ -1130,37 +765,9 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
with_lightmap = true;
}
if (with_lightmap)
{
if (m_shaders[SHADER_NORMAL_MAP_WITH_LIGHTMAP] == NULL)
{
m_shaders[SHADER_NORMAL_MAP_WITH_LIGHTMAP] =
new NormalMapProvider(true);
}
}
else
{
if (m_shaders[SHADER_NORMAL_MAP] == NULL)
{
m_shaders[SHADER_NORMAL_MAP] = new NormalMapProvider(false);
}
}
const char* vertex_shader = "normalmap.vert";
const char* pixel_shader = "normalmap.frag";
// Material and shaders
IGPUProgrammingServices* gpu =
video_driver->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + vertex_shader).c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + pixel_shader).c_str(),
"main", video::EPST_PS_2_0,
m_shaders[with_lightmap ? SHADER_NORMAL_MAP_WITH_LIGHTMAP
: SHADER_NORMAL_MAP],
video::EMT_SOLID_2_LAYER );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
m->MaterialType = irr_driver->getShader(
with_lightmap ? ES_NORMAL_MAP_LIGHTMAP : ES_NORMAL_MAP );
m->Lighting = false;
m->ZWriteEnable = true;
@ -1210,64 +817,20 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
}
m->setTexture(5, tex);
if (m_splatting_lightmap.size() > 0)
{
tex = irr_driver->getTexture(m_splatting_lightmap);
}
m->setTexture(6, tex);
if (m_splatting_lightmap.size() > 0)
{
if (m_shaders[SHADER_SPLATTING_LIGHTMAP] == NULL)
{
m_shaders[SHADER_SPLATTING_LIGHTMAP] =
new SplattingProvider(true);
}
}
else
{
if (m_shaders[SHADER_SPLATTING] == NULL)
{
m_shaders[SHADER_SPLATTING] = new SplattingProvider(false);
}
}
// Material and shaders
IGPUProgrammingServices* gpu =
irr_driver->getVideoDriver()->getGPUProgrammingServices();
if (m_splatting_lightmap.size() > 0)
{
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir()
+ "splatting_lightmap.vert").c_str(),
"main",video::EVST_VS_2_0,
(file_manager->getShaderDir()
+ "splatting_lightmap.frag").c_str(),
"main",video::EPST_PS_2_0,
m_shaders[SHADER_SPLATTING_LIGHTMAP],
video::EMT_SOLID );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
}
else
{
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir()
+ "splatting.vert").c_str(),
"main",video::EVST_VS_2_0,
(file_manager->getShaderDir()
+ "splatting.frag").c_str(),
"main",video::EPST_PS_2_0,
m_shaders[SHADER_SPLATTING], video::EMT_SOLID );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
}
m->MaterialType = irr_driver->getShader(ES_SPLATTING);
}
else
{
m->MaterialType = video::EMT_SOLID;
}
}
if (m_graphical_effect == GE_CAUSTICS && irr_driver->isGLSL())
{
m->MaterialType = irr_driver->getShader(ES_CAUSTICS);
m->setTexture(1, irr_driver->getTexture((file_manager->getTextureDir() + "caustics.png").c_str()));
}
// Modify lightmap materials so that vertex colors are taken into account.
@ -1284,26 +847,14 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_graphical_effect == GE_BUBBLE && mb != NULL)
{
IVideoDriver* video_driver = irr_driver->getVideoDriver();
if (UserConfigParams::m_pixel_shaders &&
irr_driver->isGLSL())
if (irr_driver->isGLSL())
{
if (m_bubble_provider.find(mb) == m_bubble_provider.end())
{
m_bubble_provider[mb] = new BubbleEffectProvider();
}
BubbleEffectProvider * bubble = (BubbleEffectProvider *)
irr_driver->getCallback(ES_BUBBLES);
bubble->addBubble(mb);
// Material and shaders
IGPUProgrammingServices* gpu = video_driver->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + "bubble.vert").c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + "bubble.frag").c_str(),
"main", video::EPST_PS_2_0,
m_bubble_provider[mb],
(m_alpha_blending ? video::EMT_TRANSPARENT_ALPHA_CHANNEL
: video::EMT_SOLID) );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
m->MaterialType = irr_driver->getShader(ES_BUBBLES);
m->BlendOperation = video::EBO_ADD;
// alpha blending and bubble shading can work together so when both are enabled
// don't increment the 'modes' counter to not get the 'too many modes' warning
@ -1317,70 +868,40 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_graphical_effect == GE_WATER_SHADER)
{
if (UserConfigParams::m_pixel_shaders &&
irr_driver->isGLSL())
if (irr_driver->isGLSL())
{
if (m_shaders[SHADER_WATER] == NULL)
{
m_shaders[SHADER_WATER] =
new WaterShaderProvider(m_water_shader_speed_1,
m_water_shader_speed_2);
}
m->setTexture(1, irr_driver->getTexture(file_manager->getTextureFile("waternormals.jpg")));
m->setTexture(2, irr_driver->getTexture(file_manager->getTextureFile("waternormals2.jpg")));
bool fog = World::getWorld()->getTrack()->isFogEnabled();
const char* vertex_shader = (fog ? "water_fog.vert" : "water.vert");
const char* pixel_shader = (fog ? "water_fog.frag" : "water.frag");
((WaterShaderProvider *) irr_driver->getCallback(ES_WATER))->
setSpeed(m_water_shader_speed_1/100.0f, m_water_shader_speed_2/100.0f);
((WaterShaderProvider*)m_shaders[SHADER_WATER])->enableFog(fog);
// Material and shaders
IGPUProgrammingServices* gpu =
irr_driver->getVideoDriver()->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + vertex_shader).c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + pixel_shader ).c_str(),
"main", video::EPST_PS_2_0,
m_shaders[SHADER_WATER],
video::EMT_TRANSPARENT_ALPHA_CHANNEL);
m->MaterialType = (E_MATERIAL_TYPE)material_type;
m->MaterialType = irr_driver->getShader(ES_WATER);
}
modes++;
}
if (m_graphical_effect == GE_GRASS)
{
if (UserConfigParams::m_pixel_shaders &&
if (UserConfigParams::m_weather_effects &&
irr_driver->isGLSL())
{
if (m_shaders[SHADER_GRASS] == NULL)
{
m_shaders[SHADER_GRASS] =
new GrassShaderProvider(m_grass_amplitude, m_grass_speed);
}
bool fog = World::getWorld()->getTrack()->isFogEnabled();
((GrassShaderProvider*)m_shaders[SHADER_GRASS])->enableFog(fog);
grass_shaders_times[grass_shaders_times_index] = (rand() % 500)/500.0f * M_PI * 2.0f;
// Only one grass speed & amplitude per map for now
((GrassShaderProvider *) irr_driver->getCallback(ES_GRASS))->
setSpeed(m_grass_speed);
((GrassShaderProvider *) irr_driver->getCallback(ES_GRASS))->
setAmplitude(m_grass_amplitude);
// Material and shaders
IGPUProgrammingServices* gpu =
irr_driver->getVideoDriver()->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + "grass.vert").c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + "grass.frag").c_str(),
"main", video::EPST_PS_2_0,
m_shaders[SHADER_GRASS],
video::EMT_TRANSPARENT_ALPHA_CHANNEL,
grass_shaders_times_index);
m->MaterialType = (E_MATERIAL_TYPE)material_type;
if (m_alpha_testing)
{
m->MaterialType = irr_driver->getShader(ES_GRASS_REF);
}
else {
m->MaterialType = irr_driver->getShader(ES_GRASS);
m->BlendOperation = video::EBO_ADD;
}
grass_shaders_times_index++;
}
}
@ -1475,6 +996,10 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
void Material::adjustForFog(scene::ISceneNode* parent, video::SMaterial *m,
bool use_fog) const
{
// The new pipeline does fog as a post-process effect.
if (irr_driver->isGLSL())
return;
m->setFlag(video::EMF_FOG_ENABLE, m_fog && use_fog);
if (parent != NULL)
@ -1488,10 +1013,9 @@ void Material::adjustForFog(scene::ISceneNode* parent, video::SMaterial *m,
/** Callback from LOD nodes to create some effects */
void Material::onMadeVisible(scene::IMeshBuffer* who)
{
if (m_bubble_provider.find(who) != m_bubble_provider.end())
{
m_bubble_provider[who]->onMadeVisible();
}
BubbleEffectProvider * bubble = (BubbleEffectProvider *)
irr_driver->getCallback(ES_BUBBLES);
bubble->onMadeVisible(who);
}
//-----------------------------------------------------------------------------
@ -1499,20 +1023,18 @@ void Material::onMadeVisible(scene::IMeshBuffer* who)
/** Callback from LOD nodes to create some effects */
void Material::onHidden(scene::IMeshBuffer* who)
{
if (m_bubble_provider.find(who) != m_bubble_provider.end())
{
m_bubble_provider[who]->onHidden();
}
BubbleEffectProvider * bubble = (BubbleEffectProvider *)
irr_driver->getCallback(ES_BUBBLES);
bubble->onHidden(who);
}
//-----------------------------------------------------------------------------
void Material::isInitiallyHidden(scene::IMeshBuffer* who)
{
if (m_bubble_provider.find(who) != m_bubble_provider.end())
{
m_bubble_provider[who]->isInitiallyHidden();
}
BubbleEffectProvider * bubble = (BubbleEffectProvider *)
irr_driver->getCallback(ES_BUBBLES);
bubble->isInitiallyHidden(who);
}
//-----------------------------------------------------------------------------

View File

@ -28,8 +28,6 @@
#include <IShaderConstantSetCallBack.h>
#define LIGHTMAP_VISUALISATION 0
namespace irr
{
@ -42,10 +40,6 @@ class XMLNode;
class SFXBase;
class ParticleKind;
class NormalMapProvider;
class SplattingProvider;
class BubbleEffectProvider;
/**
* \ingroup graphics
*/
@ -60,7 +54,8 @@ public:
GE_WATER_SHADER,
GE_SPHERE_MAP,
GE_SPLATTING,
GE_NORMAL_MAP};
GE_NORMAL_MAP,
GE_CAUSTICS};
enum ParticleConditions
{
@ -80,18 +75,6 @@ public:
private:
enum Shaders
{
SHADER_NORMAL_MAP,
SHADER_NORMAL_MAP_WITH_LIGHTMAP,
SHADER_SPLATTING,
SHADER_WATER,
SHADER_SPHERE_MAP,
SHADER_SPLATTING_LIGHTMAP,
SHADER_GRASS,
SHADER_COUNT
};
video::ITexture *m_texture;
unsigned int m_index;
std::string m_texname;
@ -234,13 +217,6 @@ private:
/** If m_splatting is true, indicates the fourth splatting texture */
std::string m_splatting_texture_4;
std::string m_splatting_lightmap;
std::vector<irr::video::IShaderConstantSetCallBack*> m_shaders;
/** Only used if bubble effect is enabled */
std::map<scene::IMeshBuffer*, BubbleEffectProvider*> m_bubble_provider;
bool m_deprecated;
void init (unsigned int index);

View File

@ -60,10 +60,6 @@ MaterialManager::~MaterialManager()
m_materials.clear();
} // ~MaterialManager
#if LIGHTMAP_VISUALISATION
std::set<scene::IMeshBuffer*> g_processed;
#endif
//-----------------------------------------------------------------------------
Material* MaterialManager::getMaterialFor(video::ITexture* t,

View File

@ -0,0 +1,200 @@
#ifndef AREAMAP_H
#define AREAMAP_H
static const unsigned char AreaMap33[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa5,
0x08, 0x04, 0x00, 0x00, 0x00, 0x97, 0x22, 0xf5, 0x51, 0x00, 0x00, 0x00,
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
0x00, 0x02, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x87, 0x8f, 0xcc, 0xbf,
0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13,
0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00,
0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xdb, 0x06, 0x07, 0x09, 0x17, 0x12,
0x5f, 0x51, 0x45, 0x04, 0x00, 0x00, 0x08, 0x87, 0x49, 0x44, 0x41, 0x54,
0x78, 0xda, 0xed, 0x5d, 0x4b, 0x6e, 0xdb, 0x48, 0x14, 0x2c, 0x89, 0x2f,
0x4e, 0xe2, 0x09, 0x30, 0x9b, 0x38, 0x5b, 0xf9, 0x24, 0x73, 0xbb, 0xb9,
0x49, 0x6e, 0x32, 0x67, 0x98, 0x7d, 0xbc, 0xf2, 0xc2, 0x18, 0x78, 0x31,
0x81, 0xc6, 0xa6, 0xc4, 0xd7, 0xc3, 0x8f, 0x1a, 0x0d, 0x9a, 0x92, 0x5b,
0x64, 0x91, 0x7a, 0x1d, 0xa1, 0xab, 0x41, 0x28, 0x41, 0x80, 0x42, 0xd5,
0x63, 0x93, 0x32, 0x9c, 0x42, 0x35, 0xc0, 0x63, 0x03, 0x73, 0x6c, 0x60,
0x8f, 0x35, 0x78, 0xdc, 0xe3, 0x16, 0x2c, 0x78, 0x09, 0x57, 0x31, 0xca,
0x6f, 0xb8, 0xc3, 0x0d, 0x68, 0xd8, 0x4b, 0xb0, 0x1f, 0xe5, 0x2d, 0xbe,
0xe2, 0x77, 0x08, 0x48, 0xd8, 0x4b, 0xb0, 0x1f, 0xe5, 0x47, 0x7c, 0xa9,
0x7d, 0xfc, 0x86, 0x02, 0x06, 0x48, 0x46, 0x02, 0x64, 0x16, 0x8e, 0xcf,
0xb5, 0x8b, 0x17, 0x54, 0xd8, 0x42, 0x41, 0xc0, 0x5a, 0x82, 0xfd, 0x28,
0x0b, 0x7c, 0xac, 0x9d, 0xdc, 0x62, 0x07, 0xc5, 0x0b, 0xe1, 0xc4, 0x5c,
0x82, 0xfd, 0x28, 0xd7, 0xb8, 0xa9, 0x9d, 0x7c, 0xc2, 0x2b, 0xf6, 0x70,
0x78, 0x25, 0x9c, 0x98, 0x4b, 0xb0, 0x1f, 0xa5, 0x1c, 0x9c, 0xec, 0xa1,
0x50, 0x94, 0x70, 0x20, 0x60, 0x27, 0xc1, 0x7e, 0x94, 0x2b, 0x14, 0xf8,
0x50, 0xaf, 0xda, 0x4b, 0xeb, 0x04, 0x84, 0x13, 0x73, 0x09, 0xf6, 0xa3,
0x94, 0xd6, 0x47, 0x59, 0x3b, 0x51, 0x28, 0x1c, 0x76, 0x84, 0x13, 0x53,
0x09, 0xf6, 0xa3, 0x2c, 0xf0, 0xa1, 0xf5, 0xb2, 0xc7, 0xbe, 0xf5, 0xe1,
0xb0, 0x27, 0x9c, 0x98, 0x49, 0xb0, 0x1f, 0xe5, 0x1a, 0xd2, 0x38, 0xf1,
0x3e, 0x5a, 0x27, 0x20, 0x9c, 0x18, 0x4a, 0xb0, 0x1f, 0x65, 0xe7, 0x44,
0xda, 0x6d, 0x51, 0x1d, 0x9c, 0x38, 0x54, 0x84, 0x13, 0x13, 0x09, 0xf6,
0xa3, 0xf4, 0x4e, 0xe4, 0xe0, 0xc4, 0xfb, 0x00, 0xe1, 0xc4, 0x40, 0x82,
0xfd, 0x28, 0x81, 0x35, 0x8a, 0x6e, 0xb5, 0x3e, 0x2a, 0x54, 0x84, 0x13,
0x53, 0x09, 0xf6, 0xbb, 0xd2, 0x6f, 0x8a, 0xe0, 0x26, 0xf8, 0x70, 0xa8,
0xc0, 0x23, 0x7d, 0x09, 0x90, 0x79, 0x9c, 0xf4, 0x3c, 0x54, 0xa8, 0xda,
0x4f, 0x77, 0x58, 0x20, 0x9c, 0x18, 0x48, 0xb0, 0x1f, 0xa5, 0xf7, 0xb2,
0x46, 0xd8, 0x14, 0xda, 0xba, 0x00, 0xe1, 0xc4, 0x48, 0x82, 0xfd, 0x03,
0x1e, 0x9e, 0x30, 0x6d, 0x2f, 0x47, 0x6c, 0x8b, 0x5f, 0x4d, 0x02, 0x64,
0x36, 0x27, 0xc1, 0xc5, 0x3a, 0xf8, 0x68, 0x2e, 0x62, 0x5b, 0x18, 0x48,
0xb0, 0x1e, 0x25, 0x06, 0x9b, 0xa2, 0x7a, 0xe3, 0xc3, 0x2d, 0xe8, 0x84,
0x90, 0x90, 0xe6, 0xbb, 0xb2, 0xbf, 0x0a, 0x68, 0xbb, 0x0a, 0xb8, 0x76,
0x15, 0x40, 0xfb, 0xa9, 0x60, 0xc1, 0x4b, 0x48, 0xfb, 0x5d, 0x39, 0xd8,
0x14, 0x55, 0xf7, 0x19, 0x5e, 0x54, 0x07, 0x2f, 0x20, 0x9c, 0x18, 0x48,
0xb0, 0x7a, 0xc0, 0xfb, 0x4e, 0xb4, 0x59, 0xfe, 0x6f, 0xde, 0x05, 0xe1,
0x24, 0x79, 0x09, 0x32, 0xf3, 0x17, 0xa8, 0x77, 0x12, 0xf4, 0xf7, 0x9f,
0x2e, 0x47, 0x38, 0x31, 0x90, 0x60, 0xbd, 0x2b, 0x87, 0xab, 0xf0, 0x5e,
0x88, 0x6d, 0x91, 0xbc, 0x04, 0x99, 0xd7, 0xc5, 0x09, 0x2f, 0xae, 0xbd,
0xc2, 0x96, 0x70, 0x11, 0x27, 0x56, 0x12, 0xec, 0xbf, 0x76, 0x06, 0x4f,
0x58, 0x70, 0x13, 0x5e, 0x53, 0x7d, 0x17, 0x88, 0x38, 0xb1, 0x95, 0x60,
0xbf, 0x2b, 0x7b, 0x0e, 0x56, 0x6f, 0x36, 0x44, 0xe1, 0x5d, 0xb4, 0x9f,
0x8e, 0x70, 0x62, 0x20, 0xc1, 0xe0, 0x5d, 0x79, 0xf4, 0x09, 0x53, 0xac,
0xfb, 0xef, 0x7d, 0x62, 0x5b, 0x24, 0x2c, 0x41, 0xe6, 0x77, 0x32, 0xfc,
0x1a, 0xed, 0xd4, 0x7b, 0x3f, 0xde, 0x07, 0xe1, 0x24, 0x49, 0x09, 0x32,
0xf7, 0x4f, 0xc8, 0xde, 0x4b, 0xcf, 0x55, 0x70, 0xb1, 0x1e, 0xf8, 0x70,
0x70, 0xd7, 0x21, 0x61, 0x85, 0x0d, 0xee, 0xf1, 0x0d, 0xb7, 0xf8, 0x08,
0x41, 0x71, 0xb8, 0x9d, 0x61, 0x85, 0x37, 0x3a, 0xfc, 0xe7, 0xe0, 0x4f,
0x7f, 0x61, 0x45, 0x32, 0xfc, 0x09, 0x12, 0x9b, 0xcd, 0x03, 0xe9, 0x62,
0xf3, 0x9d, 0x65, 0x10, 0x3c, 0xe0, 0x09, 0x77, 0xf8, 0x8a, 0x2f, 0xf8,
0x5c, 0xd3, 0xdc, 0xb4, 0x44, 0x85, 0x27, 0xeb, 0x11, 0x22, 0x90, 0xf6,
0xc8, 0x57, 0xf8, 0x1b, 0x3f, 0x28, 0x06, 0x1a, 0xf7, 0x0f, 0x4f, 0x4f,
0x5b, 0xca, 0x05, 0xcf, 0x20, 0x00, 0xb6, 0x78, 0xc4, 0xb6, 0xcd, 0xd4,
0x75, 0x24, 0x1f, 0x5a, 0x1a, 0x69, 0x49, 0x8a, 0x37, 0x3f, 0x5d, 0xe0,
0x08, 0xe1, 0x37, 0xfc, 0xc0, 0x3f, 0x0c, 0xc3, 0x2c, 0x51, 0xd5, 0xed,
0xe3, 0x63, 0x49, 0x68, 0xe0, 0x19, 0x04, 0x0d, 0x4a, 0x3c, 0xd7, 0xd7,
0x0b, 0x6e, 0xf1, 0xa9, 0x26, 0xf9, 0xd0, 0xae, 0x8e, 0xa4, 0xe8, 0xd1,
0xd4, 0xd7, 0x60, 0x75, 0x39, 0xd1, 0x2d, 0xfe, 0x25, 0x18, 0x38, 0x78,
0x09, 0xe5, 0xf3, 0xf3, 0x7e, 0xb2, 0x06, 0x9e, 0x41, 0xd0, 0x61, 0x8f,
0x9f, 0xa8, 0xb0, 0xc3, 0x6b, 0x4d, 0x72, 0x53, 0x2f, 0x39, 0x90, 0x14,
0x07, 0x1a, 0xbf, 0x56, 0x43, 0xa2, 0x43, 0x4e, 0xb4, 0xc4, 0x7f, 0x93,
0x19, 0x58, 0x78, 0x09, 0xfb, 0x9f, 0x3f, 0xab, 0x89, 0x1a, 0x78, 0x06,
0x81, 0x47, 0x97, 0xf2, 0xdc, 0xd7, 0xeb, 0x23, 0xca, 0xf6, 0x7e, 0x88,
0x7f, 0x5f, 0xf4, 0x49, 0x06, 0xf7, 0xe5, 0x16, 0x3e, 0x27, 0xfa, 0x32,
0x8d, 0x61, 0xc6, 0xa8, 0x6a, 0xb5, 0xdd, 0xea, 0x24, 0x0d, 0x73, 0x30,
0x04, 0x68, 0xcd, 0xe4, 0xa0, 0x0d, 0x49, 0x4b, 0x25, 0x81, 0x24, 0xdc,
0x93, 0x01, 0xc9, 0xba, 0x97, 0x13, 0x2d, 0xa7, 0x30, 0xcc, 0x1a, 0x55,
0xd5, 0x97, 0x17, 0x9d, 0xa0, 0x81, 0x67, 0x90, 0x9e, 0x22, 0xc5, 0x2b,
0xb4, 0x59, 0x2d, 0x85, 0xbf, 0x1f, 0xd2, 0x12, 0x78, 0x8a, 0x21, 0x4d,
0x3f, 0x27, 0xba, 0x1b, 0xcf, 0x30, 0x73, 0x54, 0x55, 0x5f, 0x5f, 0x75,
0xb4, 0x06, 0x9e, 0x41, 0xd0, 0x87, 0xa2, 0x04, 0xd0, 0xd1, 0x54, 0x6d,
0xf8, 0xa6, 0x40, 0xd5, 0x11, 0x9c, 0x22, 0x19, 0xe4, 0x44, 0x77, 0x63,
0x19, 0x66, 0x8f, 0xaa, 0x6a, 0x59, 0xba, 0x91, 0x1a, 0x78, 0x06, 0xc1,
0x5b, 0x38, 0x94, 0x70, 0xf5, 0xf2, 0x34, 0xd2, 0x50, 0x44, 0xb6, 0xf7,
0xdb, 0x9c, 0xe8, 0x6e, 0x1c, 0xc3, 0x02, 0x51, 0x55, 0x57, 0x8f, 0x62,
0x94, 0x06, 0x9e, 0x41, 0x30, 0x84, 0xeb, 0x8d, 0x42, 0xfd, 0xff, 0xce,
0xfb, 0x3b, 0xe3, 0x29, 0x02, 0xd1, 0x91, 0x9c, 0xe8, 0x7e, 0x0c, 0xc3,
0x22, 0x51, 0x55, 0xb7, 0xdb, 0xb9, 0x11, 0x1a, 0x78, 0x06, 0xc1, 0x11,
0xb4, 0xa3, 0x00, 0x3c, 0x8d, 0x34, 0x34, 0xed, 0x52, 0xac, 0x9b, 0xab,
0x4f, 0x72, 0x22, 0x27, 0x5a, 0xa1, 0x3c, 0x97, 0x61, 0xa1, 0xa8, 0xaa,
0xdb, 0xef, 0xdd, 0xd9, 0x2e, 0x78, 0x06, 0xc1, 0x71, 0x74, 0xfb, 0xca,
0x2f, 0xf5, 0x2b, 0x50, 0x04, 0xa2, 0x13, 0x39, 0xd1, 0x12, 0xd5, 0xb9,
0x0c, 0x8b, 0x45, 0x55, 0x9b, 0x51, 0x9c, 0xa9, 0x81, 0x67, 0x10, 0x1c,
0x87, 0x8f, 0x7f, 0x79, 0x0a, 0xff, 0x59, 0x34, 0x57, 0x9f, 0xe2, 0x9d,
0x9c, 0xa8, 0x62, 0x77, 0x0e, 0xc3, 0x82, 0x51, 0x55, 0x57, 0x55, 0xee,
0x2c, 0x17, 0x3c, 0x83, 0x00, 0x91, 0x61, 0x06, 0x1a, 0x45, 0xd1, 0xfd,
0x8e, 0xaa, 0x4f, 0xf1, 0x4e, 0x4e, 0x74, 0x07, 0xc5, 0x3e, 0xce, 0xb0,
0x68, 0x54, 0xb5, 0x1d, 0x45, 0x5c, 0x03, 0xcf, 0x20, 0x40, 0x64, 0x98,
0x2d, 0x1b, 0x9c, 0x5f, 0x03, 0x8a, 0xf5, 0xbb, 0x39, 0xd1, 0x3d, 0x14,
0xbb, 0x18, 0xc3, 0x62, 0x51, 0xd5, 0x30, 0x8a, 0xa8, 0x0b, 0x9e, 0x41,
0x80, 0xe8, 0x30, 0x71, 0x94, 0xa2, 0x80, 0xeb, 0xde, 0x17, 0x91, 0x9c,
0xe8, 0x2e, 0xce, 0xb0, 0x78, 0x54, 0xd5, 0x55, 0x51, 0x0d, 0x3c, 0x83,
0x20, 0x8e, 0xaa, 0xa5, 0xf0, 0x44, 0x45, 0x77, 0x75, 0x44, 0xed, 0x67,
0x3c, 0x27, 0x1a, 0x67, 0x58, 0x3e, 0xaa, 0x1a, 0xd1, 0xc0, 0x33, 0x08,
0xce, 0x81, 0xbf, 0x23, 0x05, 0xd0, 0x11, 0xf4, 0x62, 0x0f, 0x91, 0x9c,
0x68, 0x9c, 0xe1, 0x42, 0x51, 0xd5, 0x88, 0x06, 0x96, 0x41, 0x80, 0x11,
0xc3, 0x0c, 0x34, 0xcd, 0xea, 0x48, 0xf4, 0x9c, 0x9c, 0x68, 0x84, 0xe1,
0x52, 0x51, 0xd5, 0x77, 0x34, 0xf0, 0x0c, 0x82, 0x73, 0x51, 0xf5, 0xee,
0x87, 0x27, 0x51, 0xac, 0xe3, 0x39, 0xd1, 0x18, 0xc3, 0x05, 0xa3, 0xaa,
0x27, 0x35, 0xf0, 0x0c, 0x82, 0xf3, 0x51, 0x21, 0x44, 0x1b, 0x3c, 0xf7,
0x1a, 0xee, 0xbc, 0x9c, 0x68, 0x84, 0xe1, 0x72, 0x51, 0xd5, 0x13, 0x1a,
0x78, 0x06, 0xc1, 0x18, 0x28, 0x02, 0x05, 0x0e, 0x44, 0xeb, 0xb1, 0x39,
0xd1, 0x21, 0xc3, 0x85, 0xa3, 0xaa, 0x47, 0x35, 0xf0, 0x0c, 0x82, 0x71,
0x50, 0x04, 0xb8, 0x6e, 0x11, 0x39, 0x51, 0xff, 0xaf, 0x97, 0x8e, 0xaa,
0x1e, 0xd1, 0xc0, 0x33, 0x08, 0x30, 0x71, 0x98, 0xce, 0xaf, 0xa9, 0x39,
0xd1, 0xc0, 0x60, 0x10, 0x55, 0x1d, 0x68, 0xe0, 0x19, 0x04, 0x98, 0x34,
0x4c, 0x47, 0xe7, 0x44, 0x9d, 0x71, 0x54, 0xd5, 0x6b, 0x20, 0x19, 0xd8,
0xa0, 0x8b, 0xf6, 0xee, 0xc7, 0xc4, 0x9c, 0x68, 0x60, 0x30, 0x8a, 0xaa,
0xf6, 0x34, 0xf0, 0x0c, 0x82, 0x69, 0xd0, 0xab, 0x88, 0xaa, 0xea, 0x9c,
0x0c, 0x82, 0xa9, 0xd0, 0xab, 0x88, 0xaa, 0xea, 0x7c, 0x0c, 0x42, 0xe8,
0xd7, 0xab, 0x88, 0xaa, 0xea, 0x5c, 0x0c, 0x02, 0x06, 0x7a, 0x15, 0x51,
0x55, 0x9d, 0x87, 0x41, 0xc0, 0x41, 0xe1, 0xe8, 0x9c, 0xa8, 0x33, 0x8f,
0xaa, 0x2a, 0x1c, 0xcf, 0x20, 0x60, 0xe1, 0xae, 0x22, 0xaa, 0xea, 0xc0,
0x33, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x83, 0x15, 0x5f, 0xaa,
0xfa, 0x7d, 0x73, 0xff, 0x60, 0x5c, 0xaa, 0x8a, 0x3f, 0xb0, 0x32, 0x77,
0x21, 0x7c, 0xa9, 0xea, 0xc3, 0xfd, 0xd3, 0xd3, 0xdd, 0x96, 0x61, 0xe0,
0xc1, 0x17, 0xbb, 0xf2, 0x2e, 0x84, 0x2f, 0x55, 0xc5, 0xb7, 0xed, 0xdd,
0xe3, 0xe3, 0xb6, 0x24, 0x18, 0x68, 0xf0, 0xc5, 0xae, 0xbc, 0x0b, 0x61,
0x4b, 0x55, 0xbb, 0x4a, 0xd3, 0x72, 0xfb, 0xfc, 0x5c, 0xee, 0x8d, 0x4a,
0x55, 0x43, 0xb1, 0xab, 0xa9, 0x0b, 0xe1, 0x4b, 0x55, 0xbb, 0x4a, 0xd3,
0x7d, 0xd9, 0xf4, 0x91, 0x1a, 0x95, 0xaa, 0x86, 0x62, 0x57, 0x43, 0x17,
0xc2, 0x97, 0xaa, 0xfa, 0x4a, 0xd3, 0xae, 0x8f, 0x74, 0x0a, 0x03, 0x0f,
0xa1, 0x8b, 0x5d, 0x79, 0x17, 0xc2, 0x97, 0xaa, 0x86, 0x4a, 0xd3, 0xa6,
0x8f, 0xd4, 0xe9, 0x78, 0x06, 0x1e, 0x7c, 0xb1, 0x2b, 0xef, 0x42, 0xe8,
0x52, 0xd5, 0x5e, 0xa5, 0xa9, 0xba, 0xa6, 0x8f, 0x74, 0x2c, 0x03, 0x0f,
0xbe, 0xd8, 0x95, 0x77, 0x21, 0x7c, 0xa9, 0x6a, 0xbf, 0xd2, 0x54, 0xb5,
0x2c, 0xe1, 0xc6, 0x31, 0xf0, 0xe0, 0x8b, 0x5d, 0x79, 0x17, 0x42, 0x97,
0xaa, 0x0e, 0x2a, 0x4d, 0x1d, 0x9a, 0x3e, 0xd2, 0x31, 0x0c, 0x3c, 0xf8,
0x62, 0x57, 0xde, 0x85, 0xf0, 0xa5, 0xaa, 0xc3, 0x4a, 0xd3, 0xae, 0x8f,
0x74, 0x04, 0x03, 0x0d, 0xbe, 0xd8, 0x95, 0x77, 0x21, 0x74, 0xa9, 0xea,
0xd1, 0x4a, 0xd3, 0xa6, 0x8f, 0x14, 0xee, 0x5c, 0x06, 0x1e, 0x7c, 0xb1,
0x2b, 0xef, 0x42, 0xe8, 0x52, 0xd5, 0x13, 0x95, 0xa6, 0x0e, 0x4d, 0x1f,
0xe9, 0x79, 0x0c, 0x3c, 0xf8, 0x62, 0x57, 0xde, 0x85, 0xd0, 0xa5, 0xaa,
0x27, 0x2b, 0x4d, 0xdb, 0xa2, 0x42, 0x77, 0x0e, 0x03, 0x0f, 0xbe, 0xd8,
0x95, 0x77, 0x21, 0x7c, 0xa9, 0xea, 0xe9, 0x4a, 0x53, 0x87, 0x46, 0x46,
0x9c, 0x81, 0x07, 0x5f, 0xec, 0xca, 0xbb, 0x10, 0xba, 0x54, 0xf5, 0x44,
0xa5, 0x69, 0x90, 0xe1, 0x5c, 0x8c, 0x81, 0x07, 0x5f, 0xec, 0xca, 0xbb,
0x10, 0xba, 0x54, 0x35, 0x52, 0x69, 0xda, 0x3c, 0x20, 0x31, 0x06, 0x1e,
0x7c, 0xb1, 0x2b, 0xef, 0x42, 0xf8, 0x52, 0xd5, 0x78, 0xa5, 0x69, 0x55,
0x45, 0x18, 0x48, 0x44, 0x25, 0x5c, 0xc4, 0x85, 0xf0, 0xa5, 0xaa, 0xf1,
0x4a, 0xd3, 0x46, 0x46, 0x84, 0x81, 0x44, 0x5c, 0xc2, 0xf2, 0x2e, 0x84,
0x2e, 0x55, 0x3d, 0xb3, 0xd2, 0xb4, 0xaa, 0x4e, 0x32, 0xcc, 0xf5, 0x80,
0x47, 0x24, 0x2c, 0xed, 0x42, 0xe8, 0x52, 0xd5, 0xb3, 0x2b, 0x4d, 0xab,
0x6a, 0xb9, 0x52, 0xd5, 0xb8, 0x84, 0xe5, 0x5d, 0x08, 0x5d, 0xaa, 0x3a,
0xa2, 0xd2, 0xb4, 0xaa, 0x16, 0x2c, 0x55, 0x8d, 0x4b, 0x58, 0xd8, 0x85,
0xd0, 0xa5, 0xaa, 0xa3, 0x2a, 0x4d, 0x55, 0x8f, 0x31, 0x5c, 0xb4, 0x55,
0x75, 0x31, 0x17, 0x42, 0x97, 0xaa, 0x8e, 0xac, 0x34, 0x55, 0x1d, 0x32,
0x5c, 0xb0, 0x55, 0x75, 0x41, 0x17, 0x42, 0x97, 0xaa, 0x8e, 0xae, 0x34,
0x55, 0x7d, 0xcb, 0x60, 0xd0, 0xaa, 0xba, 0x80, 0x0b, 0x99, 0x58, 0xaa,
0x4a, 0x55, 0x9a, 0xaa, 0x7a, 0x06, 0x93, 0x56, 0xd5, 0x85, 0x5c, 0x08,
0x5d, 0xaa, 0x3a, 0xa9, 0xd2, 0x54, 0xb5, 0xc7, 0x60, 0xd0, 0xaa, 0x3a,
0xbf, 0x0b, 0xc1, 0x24, 0x28, 0x5d, 0x69, 0xaa, 0xd6, 0xad, 0xaa, 0xb3,
0xbb, 0x10, 0x4c, 0x84, 0xd2, 0x95, 0xa6, 0x6a, 0xd9, 0xaa, 0xba, 0x80,
0x0b, 0xc1, 0x64, 0x28, 0x5d, 0x69, 0xaa, 0xb6, 0xad, 0xaa, 0x33, 0xbb,
0x10, 0x10, 0x50, 0xba, 0xd2, 0x54, 0x2d, 0x5b, 0x55, 0x67, 0x76, 0x21,
0x74, 0xa9, 0x2a, 0x59, 0x69, 0xaa, 0xea, 0x60, 0xdd, 0xaa, 0xca, 0xbb,
0x68, 0x5c, 0x08, 0x48, 0x38, 0xba, 0xd2, 0xd4, 0xd9, 0xb7, 0xaa, 0xce,
0xe2, 0x62, 0x05, 0x1a, 0x1b, 0xc3, 0xa8, 0x6a, 0xd0, 0xf0, 0x70, 0x0f,
0x63, 0x11, 0x02, 0x16, 0x49, 0x44, 0x55, 0xf9, 0xe3, 0xfb, 0x01, 0xfb,
0x51, 0x26, 0x11, 0x55, 0xe5, 0x8f, 0xef, 0xb7, 0x1f, 0x65, 0x22, 0x51,
0x55, 0xfe, 0xf8, 0xfe, 0x14, 0x46, 0x99, 0x44, 0x54, 0x95, 0x3f, 0xbe,
0x3f, 0x85, 0x51, 0x26, 0x11, 0x55, 0x25, 0x8e, 0xef, 0x4f, 0x68, 0x94,
0x49, 0x44, 0x55, 0xf9, 0xe3, 0xfb, 0x53, 0x18, 0x65, 0x12, 0x51, 0x55,
0xfe, 0xf8, 0xfe, 0x44, 0x46, 0x69, 0x1f, 0x55, 0x65, 0x8f, 0xef, 0x4f,
0x63, 0x94, 0x49, 0x44, 0x55, 0x89, 0xe3, 0xfb, 0xd3, 0x1a, 0xa5, 0x7d,
0x54, 0x95, 0x3f, 0xbe, 0x3f, 0x91, 0x51, 0xda, 0x47, 0x55, 0xf9, 0xe3,
0xfb, 0x13, 0x19, 0xa5, 0x7d, 0x54, 0x95, 0x39, 0xbe, 0x3f, 0xa9, 0x51,
0xda, 0x47, 0x55, 0x89, 0xe3, 0xfb, 0x59, 0x11, 0xf3, 0x8e, 0xd2, 0x3e,
0xaa, 0x4a, 0x1c, 0xdf, 0x9f, 0xd0, 0x28, 0x93, 0x88, 0xaa, 0xf2, 0xc7,
0xf7, 0xa7, 0x30, 0xca, 0x24, 0xa2, 0xaa, 0xdc, 0xf1, 0xfd, 0xa9, 0x8c,
0x32, 0x89, 0xa8, 0x2a, 0x7f, 0x7c, 0x7f, 0x4a, 0xa3, 0x4c, 0x3f, 0xaa,
0x1a, 0xc9, 0xaa, 0xda, 0x8f, 0x32, 0x89, 0xa8, 0x2a, 0x7f, 0x7c, 0x7f,
0x0a, 0xa3, 0x4c, 0x22, 0xaa, 0xca, 0x1f, 0xdf, 0x9f, 0xc8, 0x28, 0xed,
0xa3, 0xaa, 0xfc, 0xf1, 0xfd, 0x89, 0x8c, 0xd2, 0x3e, 0xaa, 0xca, 0x1f,
0xdf, 0x9f, 0xc2, 0x28, 0x7f, 0xc5, 0xa8, 0xaa, 0x22, 0x20, 0xa1, 0xaf,
0x9d, 0x5f, 0x33, 0xaa, 0xaa, 0x7e, 0x90, 0xf6, 0xa3, 0xfc, 0xf5, 0xa3,
0xaa, 0x8a, 0x99, 0x45, 0xc8, 0xc5, 0x73, 0xa2, 0xe9, 0x44, 0x55, 0x35,
0x8d, 0x07, 0xfc, 0x3a, 0xa2, 0xaa, 0x9a, 0xc6, 0xae, 0xbc, 0x8e, 0xa8,
0xaa, 0xa6, 0x31, 0xca, 0xeb, 0x88, 0xaa, 0x6a, 0x1a, 0xa3, 0xbc, 0x8e,
0xa8, 0xaa, 0xa6, 0x32, 0xca, 0x6b, 0x88, 0xaa, 0x6a, 0x1a, 0x5f, 0x3b,
0xd7, 0x11, 0x55, 0x75, 0xa0, 0xf1, 0x3f, 0x19, 0xc2, 0xb4, 0x90, 0x78,
0xb9, 0x76, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
0x42, 0x60, 0x82,
};
#endif

View File

@ -22,9 +22,12 @@
#include "graphics/material_manager.hpp"
#include "graphics/particle_kind.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/shaders.hpp"
#include "graphics/wind.hpp"
#include "io/file_manager.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
#include "utils/helpers.hpp"
#include <SParticle.h>
#include <IParticleAffector.h>
@ -174,6 +177,46 @@ public:
}
};
// ============================================================================
class WindAffector : public scene::IParticleAffector
{
/** (Squared) distance from camera at which a particle is completely faded out */
float m_speed;
float m_seed;
public:
WindAffector(float speed): m_speed(speed)
{
m_seed = (rand() % 1000) - 500;
}
// ------------------------------------------------------------------------
virtual void affect(u32 now, scene::SParticle* particlearray, u32 count)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 10000.0f;
core::vector3df dir = irr_driver->getWind();
dir *= m_speed * std::min(noise2d(time, m_seed), -0.2f);
for (u32 n = 0; n < count; n++)
{
scene::SParticle& cur = particlearray[n];
cur.pos += dir;
} // for n<count
} // affect
// ------------------------------------------------------------------------
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
{
// FIXME: this method seems to make sense only for built-in affectors
return scene::EPAT_FADE_OUT;
}
}; // WindAffector
// ============================================================================
@ -499,6 +542,21 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
m_node->addAffector(scale_affector);
scale_affector->drop();
}
const float windspeed = type->getWindSpeed();
if (windspeed > 0.01f)
{
WindAffector *waf = new WindAffector(windspeed);
m_node->addAffector(waf);
waf->drop();
}
const bool flips = type->getFlips();
if (flips)
{
m_node->getMaterial(0).MaterialType = irr_driver->getShader(ES_SNOW);
m_node->getMaterial(0).BlendOperation = video::EBO_ADD;
}
}
} // setParticleType

View File

@ -54,6 +54,8 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
m_has_scale_affector = NULL;
m_scale_affector_factor_x = 0.0f;
m_scale_affector_factor_y = 0.0f;
m_wind_speed = 0;
m_flips = false;
// ----- Read XML file
@ -219,6 +221,14 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
m_material_file = material_manager->getLatestMaterial()->getTexFname();
}
// ------------------------------------------------------------------------
const XMLNode* wind = xml->getNode("wind");
if (wind != NULL)
{
wind->get("speed", &m_wind_speed);
wind->get("flips", &m_flips);
}
// ------------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More