diff options
-rw-r--r-- | SConstruct | 6 | ||||
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 5 | ||||
-rw-r--r-- | source/blender/gpu/GPU_extensions.h | 32 | ||||
-rw-r--r-- | source/blender/gpu/SConscript | 4 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 8 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.c | 44 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_fixed_material.c | 191 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 2 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_fixed_fragment.glsl | 169 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_fixed_vertex.glsl | 48 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_vertex.glsl | 6 |
11 files changed, 487 insertions, 28 deletions
diff --git a/SConstruct b/SConstruct index 3f17c1c2887..93e7dc38f5f 100644 --- a/SConstruct +++ b/SConstruct @@ -527,11 +527,13 @@ if B.targets != ['cudakernels']: data_to_c_simple("release/datafiles/preview_cycles.blend") # --- glsl --- + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fixed_fragment.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fixed_vertex.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl") - data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl") - data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl") diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 6abc41759e7..faeb0f721f4 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -50,6 +50,7 @@ set(SRC intern/gpu_codegen.c intern/gpu_draw.c intern/gpu_extensions.c + intern/gpu_fixed_material.c intern/gpu_material.c GPU_buffers.h @@ -59,10 +60,12 @@ set(SRC intern/gpu_codegen.h ) +data_to_c_simple(shaders/gpu_shader_fixed_fragment.glsl SRC) +data_to_c_simple(shaders/gpu_shader_fixed_vertex.glsl SRC) data_to_c_simple(shaders/gpu_shader_material.glsl SRC) -data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC) data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 66a7c917a55..7492304bd40 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -32,6 +32,8 @@ #ifndef __GPU_EXTENSIONS_H__ #define __GPU_EXTENSIONS_H__ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif @@ -160,17 +162,17 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels); * - only for fragment shaders now * - must call texture bind before setting a texture as uniform! */ -GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode); /*GPUShader *lib);*/ -/*GPUShader *GPU_shader_create_lib(const char *code);*/ +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines); void GPU_shader_free(GPUShader *shader); void GPU_shader_bind(GPUShader *shader); -void GPU_shader_unbind(GPUShader *shader); +void GPU_shader_unbind(void); int GPU_shader_get_uniform(GPUShader *shader, const char *name); void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, float *value); void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex); +void GPU_shader_uniform_int(GPUShader *shader, int location, int value); int GPU_shader_get_attribute(GPUShader *shader, const char *name); @@ -199,6 +201,30 @@ typedef struct GPUVertexAttribs { int totlayer; } GPUVertexAttribs; +/* Fixed Function Materials */ + +typedef enum GPUFixedMaterialOption { + GPU_FIXED_COLOR_MATERIAL = (1<<0), /* replace diffuse with glcolor */ + GPU_FIXED_SOLID_LIGHTING = (1<<1), /* use solid lighting (only 3 directional lights) */ + GPU_FIXED_SCENE_LIGHTING = (1<<2), /* use scene lighting (up to 8 arbitrary lights) */ + GPU_FIXED_TWO_SIDED = (1<<3), /* flip normals towards viewer */ + GPU_FIXED_TEXTURE_2D = (1<<4), /* use 2D texture to replace diffuse color */ + + GPU_FIXED_OPTIONS_NUM = 5, + GPU_FIXED_OPTION_COMBINATIONS = (1<<GPU_FIXED_OPTIONS_NUM) +} GPUFixedMaterialOption; + +void GPU_fixed_materials_init(void); +void GPU_fixed_materials_exit(void); + +void GPU_fixed_material_shader_bind(int options); +void GPU_fixed_material_shader_unbind(void); + +void GPU_fixed_material_colors(const float diffuse[3], const float specular[3], + int shininess, float alpha); + +bool GPU_fixed_material_need_normals(void); + #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index f7db3dfeaa0..ccea40c0909 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -49,10 +49,12 @@ if env['WITH_BF_DDS']: # generated data files import os sources.extend(( + os.path.join(env['DATA_SOURCES'], "gpu_shader_fixed_fragment.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_fixed_vertex.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"), )) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index b27a4be9f21..59953659a2c 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -237,8 +237,6 @@ GPUFunction *GPU_lookup_function(const char *name) if (!FUNCTION_HASH) { FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh"); gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library); - /*FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH); - FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl);*/ } return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (void *)name); @@ -758,7 +756,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) } } - GPU_shader_unbind(shader); + GPU_shader_unbind(); } void GPU_pass_bind(GPUPass *pass, double time, int mipmap) @@ -820,7 +818,7 @@ void GPU_pass_unbind(GPUPass *pass) input->tex = NULL; } - GPU_shader_unbind(shader); + GPU_shader_unbind(); } /* Node Link Functions */ @@ -1368,7 +1366,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri /* generate code and compile with opengl */ fragmentcode = code_generate_fragment(nodes, outlink->output, name); vertexcode = code_generate_vertex(nodes); - shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library); /*FUNCTION_LIB);*/ + shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL); /* failed? */ if (!shader) { diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index e8e47013159..56aa4b222cb 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -205,12 +205,15 @@ void GPU_extensions_init(void) #else GG.os = GPU_OS_UNIX; #endif + + GPU_fixed_materials_init(); } void GPU_extensions_exit(void) { gpu_extensions_init = 0; GPU_codegen_exit(); + GPU_fixed_materials_exit(); } int GPU_glsl_support(void) @@ -1006,7 +1009,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b glTexCoord2d(0, 1); glVertex2f(1, -1); glEnd(); - GPU_shader_unbind(blur_shader); + GPU_shader_unbind(); } /* GPUOffScreen */ @@ -1124,13 +1127,11 @@ static void shader_print_errors(const char *task, char *log, const char *code) fprintf(stderr, "%s\n", log); } -GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, /*GPUShader *lib,*/ const char *libcode) +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines) { GLint status; GLcharARB log[5000]; - const char *fragsource[2]; GLsizei length = 0; - GLint count; GPUShader *shader; if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) @@ -1154,8 +1155,14 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, /*GPU } if (vertexcode) { + const char *source[2]; + int num_source = 0; + + if (defines) source[num_source++] = defines; + if (vertexcode) source[num_source++] = vertexcode; + glAttachObjectARB(shader->object, shader->vertex); - glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL); + glShaderSourceARB(shader->vertex, num_source, source, NULL); glCompileShaderARB(shader->vertex); glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status); @@ -1170,12 +1177,15 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, /*GPU } if (fragcode) { - count = 0; - if (libcode) fragsource[count++] = libcode; - if (fragcode) fragsource[count++] = fragcode; + const char *source[3]; + int num_source = 0; + + if (defines) source[num_source++] = defines; + if (libcode) source[num_source++] = libcode; + if (fragcode) source[num_source++] = fragcode; glAttachObjectARB(shader->object, shader->fragment); - glShaderSourceARB(shader->fragment, count, fragsource, NULL); + glShaderSourceARB(shader->fragment, num_source, source, NULL); glCompileShaderARB(shader->fragment); glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status); @@ -1254,7 +1264,7 @@ void GPU_shader_bind(GPUShader *shader) GPU_print_error("Post Shader Bind"); } -void GPU_shader_unbind(GPUShader *UNUSED(shader)) +void GPU_shader_unbind() { GPU_print_error("Pre Shader Unbind"); glUseProgramObjectARB(0); @@ -1296,6 +1306,16 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng GPU_print_error("Post Uniform Vector"); } +void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value) +{ + if (location == -1) + return; + + GPU_print_error("Pre Uniform Int"); + glUniform1iARB(location, value); + GPU_print_error("Post Uniform Int"); +} + void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex) { GLenum arbnumber; @@ -1344,12 +1364,12 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) switch (shader) { case GPU_SHADER_VSM_STORE: if (!GG.shaders.vsm_store) - GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL); + GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL); retval = GG.shaders.vsm_store; break; case GPU_SHADER_SEP_GAUSSIAN_BLUR: if (!GG.shaders.sep_gaussian_blur) - GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL); + GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL); retval = GG.shaders.sep_gaussian_blur; break; } diff --git a/source/blender/gpu/intern/gpu_fixed_material.c b/source/blender/gpu/intern/gpu_fixed_material.c new file mode 100644 index 00000000000..d5a04c88e89 --- /dev/null +++ b/source/blender/gpu/intern/gpu_fixed_material.c @@ -0,0 +1,191 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_fixed_material.c + * \ingroup gpu + */ + +/* GLSL shaders to replace fixed function OpenGL materials and lighting. These + * are deprecated in newer OpenGL versions and missing in OpenGL ES 2.0. Also, + * two sided lighting is no longer natively supported on NVidia cards which + * results in slow software fallback. + * + * Todo: + * - Replace glLight and glMaterial functions entirely with GLSL uniforms, to + * make OpenGL ES 2.0 work. + * - Replace glTexCoord and glColor with generic attributes. + * - Optimize for case where fewer than 3 or 8 lights are used. + * - Optimize for case where specular is not used. + * - Optimize for case where no texture matrix is used. + */ + +#include "GL/glew.h" + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "GPU_extensions.h" + +/* Fixed function material types */ + +static struct { + GPUShader *cached_shaders[GPU_FIXED_OPTION_COMBINATIONS]; + bool failed_shaders[GPU_FIXED_OPTION_COMBINATIONS]; + + bool need_normals; +} GPU_MATERIAL_STATE; + +/* Init / exit */ + +void GPU_fixed_materials_init() +{ + memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE)); +} + +void GPU_fixed_materials_exit() +{ + int i; + + for (i = 0; i < GPU_FIXED_OPTION_COMBINATIONS; i++) + if (GPU_MATERIAL_STATE.cached_shaders[i]) + GPU_shader_free(GPU_MATERIAL_STATE.cached_shaders[i]); +} + +/* Shader lookup / create */ + +static GPUShader *gpu_fixed_material_shader(int options) +{ + /* glsl code */ + extern char datatoc_gpu_shader_fixed_vertex_glsl[]; + extern char datatoc_gpu_shader_fixed_fragment_glsl[]; + + /* cached shaders */ + GPUShader *shader = GPU_MATERIAL_STATE.cached_shaders[options]; + + if (!shader && !GPU_MATERIAL_STATE.failed_shaders[options]) { + /* create shader if it doesn't exist yet */ + char defines[64*GPU_FIXED_OPTIONS_NUM] = ""; + + if (options & GPU_FIXED_COLOR_MATERIAL) + strcat(defines, "#define USE_COLOR\n"); + if (options & GPU_FIXED_TWO_SIDED) + strcat(defines, "#define USE_TWO_SIDED\n"); + if (options & GPU_FIXED_SOLID_LIGHTING) + strcat(defines, "#define USE_SOLID_LIGHTING\n"); + if (options & GPU_FIXED_SCENE_LIGHTING) + strcat(defines, "#define USE_SCENE_LIGHTING\n"); + if (options & GPU_FIXED_TEXTURE_2D) + strcat(defines, "#define USE_TEXTURE\n"); + + shader = GPU_shader_create( + datatoc_gpu_shader_fixed_vertex_glsl, + datatoc_gpu_shader_fixed_fragment_glsl, + NULL, defines); + + if (shader) { + /* set texture map to first texture unit */ + if (options & GPU_FIXED_TEXTURE_2D) + glUniform1i(GPU_shader_get_uniform(shader, "texture_map"), 0); + + GPU_MATERIAL_STATE.cached_shaders[options] = shader; + } + else + GPU_MATERIAL_STATE.failed_shaders[options] = true; + } + + return shader; +} + +/* Bind / unbind */ + +void GPU_fixed_material_shader_bind(int options) +{ + if (GPU_glsl_support()) { + GPUShader *shader = gpu_fixed_material_shader(options); + + if (shader) + GPU_shader_bind(shader); + } + else { + if (options & (GPU_FIXED_SOLID_LIGHTING|GPU_FIXED_SCENE_LIGHTING)) + glEnable(GL_LIGHTING); + + if (options & GPU_FIXED_TWO_SIDED) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + + if (options & GPU_FIXED_COLOR_MATERIAL) { + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + } + + if (options & GPU_FIXED_TEXTURE_2D) + glEnable(GL_TEXTURE_2D); + } + + /* temporary hack, should be solved outside of this file */ + GPU_MATERIAL_STATE.need_normals = (options & (GPU_FIXED_SOLID_LIGHTING|GPU_FIXED_SCENE_LIGHTING)); +} + +void GPU_fixed_material_shader_unbind() +{ + if (GPU_glsl_support()) { + GPU_shader_unbind(); + } + else { + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + } +} + +/* Material Colors */ + +void GPU_fixed_material_colors(const float diffuse[3], const float specular[3], + int shininess, float alpha) +{ + float gl_diffuse[4], gl_specular[4]; + + copy_v3_v3(gl_diffuse, diffuse); + gl_diffuse[3] = alpha; + + copy_v3_v3(gl_specular, specular); + gl_specular[3] = 1.0f; + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); + glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128)); +} + +bool GPU_fixed_material_need_normals() +{ + return GPU_MATERIAL_STATE.need_normals; +} + diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index b5ef27a338d..d7ac6febfb7 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1919,7 +1919,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) { if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { - GPU_shader_unbind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE)); + GPU_shader_unbind(); GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex); } diff --git a/source/blender/gpu/shaders/gpu_shader_fixed_fragment.glsl b/source/blender/gpu/shaders/gpu_shader_fixed_fragment.glsl new file mode 100644 index 00000000000..9610e0cf5aa --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fixed_fragment.glsl @@ -0,0 +1,169 @@ + +/* Options: + * + * USE_COLOR: use glColor for diffuse colors + * USE_TEXTURE: use texture for diffuse colors + * USE_SCENE_LIGHTING: use lights (up to 8) + * USE_SOLID_LIGHTING: assume 3 directional lights for solid draw mode + * USE_TWO_SIDED: flip normal towards viewer + * NO_SPECULAR: use specular component + */ + +#define NUM_SOLID_LIGHTS 3 +#define NUM_SCENE_LIGHTS 8 + +#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING) +varying vec3 varying_normal; + +#ifndef USE_SOLID_LIGHTING +varying vec3 varying_position; +#endif +#endif + +#ifdef USE_COLOR +varying vec4 varying_vertex_color; +#endif + +#ifdef USE_TEXTURE +varying vec2 varying_texture_coord; +uniform sampler2D texture_map; +#endif + +void main() +{ +#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING) + /* compute normal */ + vec3 N = normalize(varying_normal); + +#ifdef USE_TWO_SIDED + if (!gl_FrontFacing) + N = -N; +#endif + + /* compute diffuse and specular lighting */ + vec3 L_diffuse = vec3(0.0); +#ifndef NO_SPECULAR + vec3 L_specular = vec3(0.0); +#endif + +#ifdef USE_SOLID_LIGHTING + /* assume 3 directional lights */ + for (int i = 0; i < NUM_SOLID_LIGHTS; i++) { + vec3 light_direction = gl_LightSource[i].position.xyz; + + /* diffuse light */ + vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; + float diffuse_bsdf = max(dot(N, light_direction), 0.0); + L_diffuse += light_diffuse*diffuse_bsdf; + +#ifndef NO_SPECULAR + /* specular light */ + vec3 light_specular = gl_LightSource[i].specular.rgb; + vec3 H = gl_LightSource[i].halfVector.xyz; + + float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess); + L_specular += light_specular*specular_bsdf; +#endif + } +#else + /* all 8 lights, makes no assumptions, potentially slow */ + +#ifndef NO_SPECULAR + /* view vector computation, depends on orthographics or perspective */ + vec3 V = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(varying_position): vec3(0.0, 0.0, -1.0); +#endif + + for (int i = 0; i < NUM_SCENE_LIGHTS; i++) { + /* todo: this is a slow check for disabled lights */ + if (gl_LightSource[i].specular.a == 0.0) + continue; + + float intensity = 1.0; + vec3 light_direction; + + if (gl_LightSource[i].position.w == 0.0) { + /* directional light */ + light_direction = gl_LightSource[i].position.xyz; + } + else { + /* point light */ + vec3 d = gl_LightSource[i].position.xyz - varying_position; + light_direction = normalize(d); + + /* spot light cone */ + if (gl_LightSource[i].spotCutoff < 90.0) { + float cosine = max(dot(light_direction, -gl_LightSource[i].spotDirection), 0.0); + intensity = pow(cosine, gl_LightSource[i].spotExponent); + intensity *= step(gl_LightSource[i].spotCosCutoff, cosine); + } + + /* falloff */ + float distance = length(d); + + intensity /= gl_LightSource[i].constantAttenuation + + gl_LightSource[i].linearAttenuation * distance + + gl_LightSource[i].quadraticAttenuation * distance * distance; + } + + /* diffuse light */ + vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; + float diffuse_bsdf = max(dot(N, light_direction), 0.0); + L_diffuse += light_diffuse*diffuse_bsdf*intensity; + +#ifndef NO_SPECULAR + /* specular light */ + vec3 light_specular = gl_LightSource[i].specular.rgb; + vec3 H = normalize(light_direction - V); + + float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess); + L_specular += light_specular*specular_bsdf*intensity; +#endif + } +#endif + + /* compute diffuse color, possibly from texture or vertex colors */ + float alpha; + +#if defined(USE_TEXTURE) && defined(USE_COLOR) + vec4 texture_color = texture2D(texture_map, varying_texture_coord); + + L_diffuse *= texture_color.rgb * varying_vertex_color.rgb; + alpha = texture_color.a * varying_vertex_color.a; +#elif defined(USE_TEXTURE) + vec4 texture_color = texture2D(texture_map, varying_texture_coord); + + L_diffuse *= texture_color.rgb; + alpha = texture_color.a; +#elif defined(USE_COLOR) + L_diffuse *= varying_vertex_color.rgb; + alpha = varying_vertex_color.a; +#else + L_diffuse *= gl_FrontMaterial.diffuse.rgb; + alpha = gl_FrontMaterial.diffuse.a; +#endif + + /* sum lighting */ + vec3 L = gl_FrontLightModelProduct.sceneColor.rgb + L_diffuse; + +#ifndef NO_SPECULAR + L += L_specular*gl_FrontMaterial.specular.rgb; +#endif + + /* write out fragment color */ + gl_FragColor = vec4(L, alpha); +#else + + /* no lighting */ +#if defined(USE_TEXTURE) && defined(USE_COLOR) + gl_FragColor = texture2D(texture_map, varying_texture_coord) * varying_vertex_color; +#elif defined(USE_TEXTURE) + gl_FragColor = texture2D(texture_map, varying_texture_coord); +#elif defined(USE_COLOR) + gl_FragColor = varying_vertex_color; +#else + gl_FragColor = gl_FrontMaterial.diffuse; +#endif + +#endif +} + diff --git a/source/blender/gpu/shaders/gpu_shader_fixed_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_fixed_vertex.glsl new file mode 100644 index 00000000000..612f9cff6aa --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fixed_vertex.glsl @@ -0,0 +1,48 @@ + +#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING) +varying vec3 varying_normal; + +#ifndef USE_SOLID_LIGHTING +varying vec3 varying_position; +#endif +#endif + +#ifdef USE_COLOR +varying vec4 varying_vertex_color; +#endif + +#ifdef USE_TEXTURE +varying vec2 varying_texture_coord; +#endif + +void main() +{ + vec4 co = gl_ModelViewMatrix * gl_Vertex; + +#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING) + varying_normal = normalize(gl_NormalMatrix * gl_Normal); + +#ifndef USE_SOLID_LIGHTING + varying_position = co.xyz; +#endif +#endif + + gl_Position = gl_ProjectionMatrix * co; + +#ifdef __GLSL_CG_DATA_TYPES + // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA graphic cards. + // gl_ClipVertex works only on NVIDIA graphic cards so we have to check with + // __GLSL_CG_DATA_TYPES if a NVIDIA graphic card is used (Cg support). + // gl_ClipVerte is supported up to GLSL 1.20. + gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#endif + +#ifdef USE_COLOR + varying_vertex_color = gl_Color; +#endif + +#ifdef USE_TEXTURE + varying_texture_coord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).st; +#endif +} + diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl index 574455e42b3..9e0db44ed31 100644 --- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl @@ -14,7 +14,7 @@ void main() // gl_ClipVertex works only on NVIDIA graphic cards so we have to check with // __GLSL_CG_DATA_TYPES if a NVIDIA graphic card is used (Cg support). // gl_ClipVerte is supported up to GLSL 1.20. - #ifdef __GLSL_CG_DATA_TYPES - gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; - #endif +#ifdef __GLSL_CG_DATA_TYPES + gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; +#endif |