From b5f9746dae9c9463705f78d15dcc7d23e66cdad5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 27 Nov 2015 21:06:23 +0100 Subject: OpenGL: update simple shader API. Restore fixed function lighting code for now and control use of GLSL shader with a variable, make light types more clear, reduce state changes, some other minor tweaks. --- source/blender/gpu/GPU_simple_shader.h | 23 +++-- source/blender/gpu/intern/gpu_simple_shader.c | 137 ++++++++++++++++++++------ 2 files changed, 120 insertions(+), 40 deletions(-) (limited to 'source') diff --git a/source/blender/gpu/GPU_simple_shader.h b/source/blender/gpu/GPU_simple_shader.h index 239296209b4..b62abc6152a 100644 --- a/source/blender/gpu/GPU_simple_shader.h +++ b/source/blender/gpu/GPU_simple_shader.h @@ -41,7 +41,7 @@ extern "C" { /* Fixed Function Shader */ typedef enum GPUSimpleShaderOption { - GPU_SHADER_OVERRIDE_DIFFUSE = (1<<0), /* replace diffuse with glcolor */ + GPU_SHADER_USE_COLOR = (1<<0), /* use glColor, for lighting it replaces diffuse */ GPU_SHADER_LIGHTING = (1<<1), /* use lighting */ GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */ GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */ @@ -55,25 +55,32 @@ void GPU_simple_shaders_init(void); void GPU_simple_shaders_exit(void); void GPU_simple_shader_bind(int options); -void GPU_simple_shader_unbind(void); +int GPU_simple_shader_bound_options(void); void GPU_simple_shader_colors(const float diffuse[3], const float specular[3], int shininess, float alpha); -bool GPU_simple_shader_need_normals(void); - /* Fixed Function Lighting */ +typedef enum GPULightType { + GPU_LIGHT_POINT, + GPU_LIGHT_SPOT, + GPU_LIGHT_SUN +} GPULightType; + typedef struct GPULightData { - float position[4]; - float diffuse[4]; - float specular[4]; + GPULightType type; + + float position[3]; + float direction[3]; + + float diffuse[3]; + float specular[3]; float constant_attenuation; float linear_attenuation; float quadratic_attenuation; - float spot_direction[3]; float spot_cutoff; float spot_exponent; } GPULightData; diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_simple_shader.c index bd7746648c8..74ca23e8854 100644 --- a/source/blender/gpu/intern/gpu_simple_shader.c +++ b/source/blender/gpu/intern/gpu_simple_shader.c @@ -52,13 +52,13 @@ /* State */ -// #define NUM_OPENGL_LIGHTS 8 +static const bool USE_GLSL = false; static struct { GPUShader *cached_shaders[GPU_SHADER_OPTION_COMBINATIONS]; bool failed_shaders[GPU_SHADER_OPTION_COMBINATIONS]; - bool need_normals; + int bound_options; int lights_enabled; int lights_directional; @@ -104,7 +104,7 @@ static int detect_options() if (glIsEnabled(GL_TEXTURE_2D)) options |= GPU_SHADER_TEXTURE_2D; if (glIsEnabled(GL_COLOR_MATERIAL)) - options |= GPU_SHADER_OVERRIDE_DIFFUSE; + options |= GPU_SHADER_USE_COLOR; if (glIsEnabled(GL_LIGHTING)) options |= GPU_SHADER_LIGHTING; @@ -136,7 +136,7 @@ static GPUShader *gpu_simple_shader(int options) /* create shader if it doesn't exist yet */ char defines[64*GPU_SHADER_OPTIONS_NUM] = ""; - if (options & GPU_SHADER_OVERRIDE_DIFFUSE) + if (options & GPU_SHADER_USE_COLOR) strcat(defines, "#define USE_COLOR\n"); if (options & GPU_SHADER_TWO_SIDED) strcat(defines, "#define USE_TWO_SIDED\n"); @@ -173,18 +173,53 @@ static GPUShader *gpu_simple_shader(int options) void GPU_simple_shader_bind(int options) { - GPUShader *shader = gpu_simple_shader(options); + if (USE_GLSL) { + if (options) { + GPUShader *shader = gpu_simple_shader(options); - if (shader) - GPU_shader_bind(shader); + if (shader) + GPU_shader_bind(shader); + } + else { + GPU_shader_unbind(); + } + } + else { + int bound_options = GPU_MATERIAL_STATE.bound_options; - /* temporary hack, should be solved outside of this file */ - GPU_MATERIAL_STATE.need_normals = (options & GPU_SHADER_LIGHTING); + if (options & GPU_SHADER_LIGHTING) { + glEnable(GL_LIGHTING); + + if (options & GPU_SHADER_USE_COLOR) + glEnable(GL_COLOR_MATERIAL); + else + glDisable(GL_COLOR_MATERIAL); + + if (options & GPU_SHADER_TWO_SIDED) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + else + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + } + else if (bound_options & GPU_SHADER_LIGHTING) { + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + } + + if (options & GPU_SHADER_TEXTURE_2D) + glEnable(GL_TEXTURE_2D); + else if (bound_options & GPU_SHADER_TEXTURE_2D) + glDisable(GL_TEXTURE_2D); + } + + GPU_MATERIAL_STATE.bound_options = options; } -void GPU_simple_shader_unbind(void) +int GPU_simple_shader_bound_options(void) { - GPU_shader_unbind(); + /* ideally this should disappear, anything that uses this is making fragile + * assumptions that the simple shader is bound and not another shader */ + return GPU_MATERIAL_STATE.bound_options; } /* Material Colors */ @@ -194,10 +229,16 @@ void GPU_simple_shader_colors(const float diffuse[3], const float specular[3], { float gl_diffuse[4], gl_specular[4]; - copy_v3_v3(gl_diffuse, diffuse); + if (diffuse) + copy_v3_v3(gl_diffuse, diffuse); + else + zero_v3(gl_diffuse); gl_diffuse[3] = alpha; - copy_v3_v3(gl_specular, specular); + if (specular) + copy_v3_v3(gl_specular, specular); + else + zero_v3(gl_specular); gl_specular[3] = 1.0f; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse); @@ -205,43 +246,75 @@ void GPU_simple_shader_colors(const float diffuse[3], const float specular[3], glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128)); } -bool GPU_simple_shader_need_normals(void) -{ - return GPU_MATERIAL_STATE.need_normals; -} - void GPU_simple_shader_light_set(int light_num, GPULightData *light) { int light_bit = (1 << light_num); + /* note that light position is affected by the current modelview matrix! */ + GPU_MATERIAL_STATE.lights_enabled &= ~light_bit; GPU_MATERIAL_STATE.lights_directional &= ~light_bit; if (light) { - glEnable(GL_LIGHT0+light_num); + float position[4], diffuse[4], specular[4]; - glLightfv(GL_LIGHT0+light_num, GL_POSITION, light->position); - glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, light->diffuse); - glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, light->specular); + glEnable(GL_LIGHT0+light_num); - glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation); - glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation); - glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation); + /* position */ + if (light->type == GPU_LIGHT_SUN) { + copy_v3_v3(position, light->direction); + position[3] = 0.0f; + } + else { + copy_v3_v3(position, light->position); + position[3] = 1.0f; + } + glLightfv(GL_LIGHT0+light_num, GL_POSITION, position); + + /* energy */ + copy_v3_v3(diffuse, light->diffuse); + copy_v3_v3(specular, light->specular); + diffuse[3] = 1.0f; + specular[3] = 1.0f; + glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, specular); + + /* attenuation */ + if (light->type == GPU_LIGHT_SUN) { + glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, 1.0f); + glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, 0.0f); + glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, 0.0f); + } + else { + glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation); + glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation); + glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation); + } - glLightfv(GL_LIGHT0+light_num, GL_SPOT_DIRECTION, light->spot_direction); - glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, light->spot_cutoff); - glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, light->spot_exponent); + /* spot */ + glLightfv(GL_LIGHT0+light_num, GL_SPOT_DIRECTION, light->direction); + if (light->type == GPU_LIGHT_SPOT) { + glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, light->spot_cutoff); + glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, light->spot_exponent); + } + else { + glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, 180.0f); + glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, 0.0f); + } GPU_MATERIAL_STATE.lights_enabled |= light_bit; if (light->position[3] == 0.0f) GPU_MATERIAL_STATE.lights_directional |= light_bit; } else { - const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + if (USE_GLSL) { + /* glsl shader needs these zero to skip them */ + const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - glLightfv(GL_LIGHT0+light_num, GL_POSITION, zero); - glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, zero); - glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, zero); + glLightfv(GL_LIGHT0+light_num, GL_POSITION, zero); + glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, zero); + glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, zero); + } glDisable(GL_LIGHT0+light_num); } -- cgit v1.2.3