diff --git a/gles/cogl-fixed-fragment-shader.glsl b/gles/cogl-fixed-fragment-shader.glsl index 9dd22b8c4..f32135399 100644 --- a/gles/cogl-fixed-fragment-shader.glsl +++ b/gles/cogl-fixed-fragment-shader.glsl @@ -1,12 +1,17 @@ /* Inputs from the vertex shader */ -varying vec4 frag_color; -varying vec2 tex_coord; +varying vec4 frag_color; +varying vec2 tex_coord; +varying float fog_amount; /* Texturing options */ uniform bool texture_2d_enabled; uniform sampler2D texture_unit; uniform bool alpha_only; +/* Fogging options */ +uniform bool fog_enabled; +uniform vec4 fog_color; + void main (void) { @@ -26,4 +31,8 @@ main (void) } else gl_FragColor = frag_color; + + if (fog_enabled) + /* Mix the calculated color with the fog color */ + gl_FragColor.rgb = mix (fog_color.rgb, gl_FragColor.rgb, fog_amount); } diff --git a/gles/cogl-fixed-vertex-shader.glsl b/gles/cogl-fixed-vertex-shader.glsl index ae6288c16..7fed8439d 100644 --- a/gles/cogl-fixed-vertex-shader.glsl +++ b/gles/cogl-fixed-vertex-shader.glsl @@ -1,15 +1,29 @@ /* Per vertex attributes */ -attribute vec4 vertex_attrib; -attribute vec4 tex_coord_attrib; -attribute vec4 color_attrib; +attribute vec4 vertex_attrib; +attribute vec4 tex_coord_attrib; +attribute vec4 color_attrib; /* Transformation matrices */ -uniform mat4 mvp_matrix; /* combined modelview and projection matrix */ -uniform mat4 texture_matrix; +uniform mat4 modelview_matrix; +uniform mat4 mvp_matrix; /* combined modelview and projection matrix */ +uniform mat4 texture_matrix; /* Outputs to the fragment shader */ -varying vec4 frag_color; -varying vec2 tex_coord; +varying vec4 frag_color; +varying vec2 tex_coord; +varying float fog_amount; + +/* Fogging options */ +uniform bool fog_enabled; +uniform int fog_mode; +uniform float fog_density; +uniform float fog_start; +uniform float fog_end; + +/* Fogging modes */ +const int GL_LINEAR = 0x2601; +const int GL_EXP = 0x0800; +const int GL_EXP2 = 0x0801; void main (void) @@ -23,4 +37,24 @@ main (void) /* Pass the interpolated vertex color on to the fragment shader */ frag_color = color_attrib; + + if (fog_enabled) + { + /* Estimate the distance from the eye using just the + z-coordinate to use as the fog coord */ + vec4 eye_coord = modelview_matrix * vertex_attrib; + float fog_coord = abs (eye_coord.z / eye_coord.w); + + /* Calculate the fog amount per-vertex and interpolate it for + the fragment shader */ + if (fog_mode == GL_EXP) + fog_amount = exp (-fog_density * fog_coord); + else if (fog_mode == GL_EXP2) + fog_amount = exp (-fog_density * fog_coord + * fog_density * fog_coord); + else + fog_amount = (fog_end - fog_coord) / (fog_end - fog_start); + + fog_amount = clamp (fog_amount, 0.0, 1.0); + } } diff --git a/gles/cogl-gles2-wrapper.c b/gles/cogl-gles2-wrapper.c index f7df08801..6a09898ca 100644 --- a/gles/cogl-gles2-wrapper.c +++ b/gles/cogl-gles2-wrapper.c @@ -84,6 +84,7 @@ void cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) { GLint status; + GLfixed default_fog_color[4] = { 0, 0, 0, 0 }; memset (wrapper, 0, sizeof (CoglGles2Wrapper)); @@ -139,6 +140,8 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) wrapper->mvp_matrix_uniform = glGetUniformLocation (wrapper->program, "mvp_matrix"); + wrapper->modelview_matrix_uniform + = glGetUniformLocation (wrapper->program, "modelview_matrix"); wrapper->texture_matrix_uniform = glGetUniformLocation (wrapper->program, "texture_matrix"); wrapper->texture_2d_enabled_uniform @@ -148,6 +151,19 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) wrapper->alpha_only_uniform = glGetUniformLocation (wrapper->program, "alpha_only"); + wrapper->fog_enabled_uniform + = glGetUniformLocation (wrapper->program, "fog_enabled"); + wrapper->fog_mode_uniform + = glGetUniformLocation (wrapper->program, "fog_mode"); + wrapper->fog_density_uniform + = glGetUniformLocation (wrapper->program, "fog_density"); + wrapper->fog_start_uniform + = glGetUniformLocation (wrapper->program, "fog_start"); + wrapper->fog_end_uniform + = glGetUniformLocation (wrapper->program, "fog_end"); + wrapper->fog_color_uniform + = glGetUniformLocation (wrapper->program, "fog_color"); + /* Always use the first texture unit */ glUniform1i (wrapper->bound_texture_uniform, 0); @@ -160,6 +176,14 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) cogl_wrap_glLoadIdentity (); wrapper->mvp_uptodate = GL_FALSE; + + /* Initialize the fogging options */ + cogl_wrap_glDisable (GL_FOG); + cogl_wrap_glFogx (GL_FOG_MODE, GL_LINEAR); + cogl_wrap_glFogx (GL_FOG_DENSITY, CFX_ONE); + cogl_wrap_glFogx (GL_FOG_START, 0); + cogl_wrap_glFogx (GL_FOG_END, 1); + cogl_wrap_glFogxv (GL_FOG_COLOR, default_fog_color); } void @@ -487,14 +511,17 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count) if (!w->mvp_uptodate) { float mvp_matrix[16]; + const float *modelview_matrix = w->modelview_stack + + w->modelview_stack_pos * 16; cogl_gles2_wrapper_mult_matrix (mvp_matrix, w->projection_stack + w->projection_stack_pos * 16, - w->modelview_stack - + w->modelview_stack_pos * 16); + modelview_matrix); glUniformMatrix4fv (w->mvp_matrix_uniform, 1, GL_FALSE, mvp_matrix); + glUniformMatrix4fv (w->modelview_matrix_uniform, 1, GL_FALSE, + modelview_matrix); w->mvp_uptodate = GL_TRUE; } @@ -536,6 +563,10 @@ cogl_wrap_glEnable (GLenum cap) glUniform1i (w->texture_2d_enabled_uniform, GL_TRUE); break; + case GL_FOG: + glUniform1i (w->fog_enabled_uniform, GL_TRUE); + break; + default: glEnable (cap); } @@ -552,6 +583,10 @@ cogl_wrap_glDisable (GLenum cap) glUniform1i (w->texture_2d_enabled_uniform, GL_FALSE); break; + case GL_FOG: + glUniform1i (w->fog_enabled_uniform, GL_FALSE); + break; + default: glDisable (cap); } @@ -654,13 +689,39 @@ cogl_wrap_glGetFixedv (GLenum pname, GLfixed *params) void cogl_wrap_glFogx (GLenum pname, GLfixed param) { - /* FIXME */ + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + switch (pname) + { + case GL_FOG_MODE: + glUniform1i (w->fog_mode_uniform, param); + break; + + case GL_FOG_DENSITY: + glUniform1f (w->fog_density_uniform, CLUTTER_FIXED_TO_FLOAT (param)); + break; + + case GL_FOG_START: + glUniform1f (w->fog_start_uniform, CLUTTER_FIXED_TO_FLOAT (param)); + break; + + case GL_FOG_END: + glUniform1f (w->fog_end_uniform, CLUTTER_FIXED_TO_FLOAT (param)); + break; + } } void cogl_wrap_glFogxv (GLenum pname, const GLfixed *params) { - /* FIXME */ + _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); + + if (pname == GL_FOG_COLOR) + glUniform4f (w->fog_color_uniform, + CLUTTER_FIXED_TO_FLOAT (params[0]), + CLUTTER_FIXED_TO_FLOAT (params[1]), + CLUTTER_FIXED_TO_FLOAT (params[2]), + CLUTTER_FIXED_TO_FLOAT (params[3])); } void diff --git a/gles/cogl-gles2-wrapper.h b/gles/cogl-gles2-wrapper.h index 81d4495d5..b1adf8ca7 100644 --- a/gles/cogl-gles2-wrapper.h +++ b/gles/cogl-gles2-wrapper.h @@ -44,11 +44,19 @@ struct _CoglGles2Wrapper GLuint fragment_shader; GLint mvp_matrix_uniform; + GLint modelview_matrix_uniform; GLint texture_matrix_uniform; GLint texture_2d_enabled_uniform; GLint bound_texture_uniform; GLint alpha_only_uniform; + GLint fog_enabled_uniform; + GLint fog_mode_uniform; + GLint fog_density_uniform; + GLint fog_start_uniform; + GLint fog_end_uniform; + GLint fog_color_uniform; + GLuint matrix_mode; GLfloat modelview_stack[COGL_GLES2_MODELVIEW_STACK_SIZE * 16]; GLuint modelview_stack_pos;