forked from bartvdbraak/blender
OpenSubdiv: Optimize drawing shader
The idea is to cut as much code as possible and use compile-time ifdefs rather than runtime if() statements. Gives about 2x speedup on catmark_car model from OpenSubdiv repository making our FPS much closer to what glViewer is capable of.
This commit is contained in:
parent
cff288cf3a
commit
abb976ae88
@ -215,8 +215,6 @@ uniform vec4 specular;
|
||||
uniform float shininess;
|
||||
|
||||
uniform sampler2D texture_buffer;
|
||||
uniform bool use_color_material;
|
||||
uniform bool use_texture_2d;
|
||||
|
||||
in block {
|
||||
VertexData v;
|
||||
@ -236,99 +234,89 @@ void main()
|
||||
vec3 L_diffuse = vec3(0.0);
|
||||
vec3 L_specular = vec3(0.0);
|
||||
|
||||
if (use_color_material == false) {
|
||||
/* Assume NUM_SOLID_LIGHTS directional lights. */
|
||||
for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
|
||||
vec3 light_direction = lightSource[i].position.xyz;
|
||||
|
||||
/* Diffuse light. */
|
||||
vec3 light_diffuse = lightSource[i].diffuse.rgb;
|
||||
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
|
||||
L_diffuse += light_diffuse * diffuse_bsdf;
|
||||
|
||||
/* Specular light. */
|
||||
vec4 Plight = lightSource[i].position;
|
||||
vec3 l = (Plight.w == 0.0)
|
||||
? normalize(Plight.xyz) : normalize(Plight.xyz -
|
||||
inpt.v.position.xyz);
|
||||
vec3 light_specular = lightSource[i].specular.rgb;
|
||||
vec3 H = normalize(l + vec3(0,0,1));
|
||||
float specular_bsdf = pow(max(dot(N, H), 0.0),
|
||||
shininess);
|
||||
L_specular += light_specular * specular_bsdf;
|
||||
}
|
||||
#ifndef USE_COLOR_MATERIAL
|
||||
/* Assume NUM_SOLID_LIGHTS directional lights. */
|
||||
for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
|
||||
vec4 Plight = lightSource[i].position;
|
||||
#ifdef USE_DIRECTIONAL_LIGHT
|
||||
vec3 l = (Plight.w == 0.0)
|
||||
? normalize(Plight.xyz)
|
||||
: normalize(inpt.v.position.xyz);
|
||||
#else /* USE_DIRECTIONAL_LIGHT */
|
||||
/* TODO(sergey): We can normalize it outside of the shader. */
|
||||
vec3 l = normalize(Plight.xyz);
|
||||
#endif /* USE_DIRECTIONAL_LIGHT */
|
||||
vec3 h = normalize(l + vec3(0, 0, 1));
|
||||
float d = max(0.0, dot(N, l));
|
||||
float s = pow(max(0.0, dot(N, h)), 500.0f);
|
||||
L_diffuse += d * lightSource[i].diffuse;
|
||||
L_specular += s * lightSource[i].specular;
|
||||
}
|
||||
else {
|
||||
vec3 varying_position = inpt.v.position.xyz;
|
||||
vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
|
||||
normalize(varying_position): vec3(0.0, 0.0, -1.0);
|
||||
for (int i = 0; i < num_enabled_lights; i++) {
|
||||
/* todo: this is a slow check for disabled lights */
|
||||
if (lightSource[i].specular.a == 0.0)
|
||||
continue;
|
||||
#else /* USE_COLOR_MATERIAL */
|
||||
vec3 varying_position = inpt.v.position.xyz;
|
||||
vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
|
||||
normalize(varying_position): vec3(0.0, 0.0, -1.0);
|
||||
for (int i = 0; i < num_enabled_lights; i++) {
|
||||
/* todo: this is a slow check for disabled lights */
|
||||
if (lightSource[i].specular.a == 0.0)
|
||||
continue;
|
||||
|
||||
float intensity = 1.0;
|
||||
vec3 light_direction;
|
||||
float intensity = 1.0;
|
||||
vec3 light_direction;
|
||||
|
||||
if (lightSource[i].position.w == 0.0) {
|
||||
/* directional light */
|
||||
light_direction = lightSource[i].position.xyz;
|
||||
}
|
||||
else {
|
||||
/* point light */
|
||||
vec3 d = lightSource[i].position.xyz - varying_position;
|
||||
light_direction = normalize(d);
|
||||
if (lightSource[i].position.w == 0.0) {
|
||||
/* directional light */
|
||||
light_direction = lightSource[i].position.xyz;
|
||||
}
|
||||
else {
|
||||
/* point light */
|
||||
vec3 d = lightSource[i].position.xyz - varying_position;
|
||||
light_direction = normalize(d);
|
||||
|
||||
/* spot light cone */
|
||||
if (lightSource[i].spotCutoff < 90.0) {
|
||||
float cosine = max(dot(light_direction,
|
||||
-lightSource[i].spotDirection.xyz),
|
||||
0.0);
|
||||
intensity = pow(cosine, lightSource[i].spotExponent);
|
||||
intensity *= step(lightSource[i].spotCosCutoff, cosine);
|
||||
}
|
||||
|
||||
/* falloff */
|
||||
float distance = length(d);
|
||||
|
||||
intensity /= lightSource[i].constantAttenuation +
|
||||
lightSource[i].linearAttenuation * distance +
|
||||
lightSource[i].quadraticAttenuation * distance * distance;
|
||||
/* spot light cone */
|
||||
if (lightSource[i].spotCutoff < 90.0) {
|
||||
float cosine = max(dot(light_direction,
|
||||
-lightSource[i].spotDirection.xyz),
|
||||
0.0);
|
||||
intensity = pow(cosine, lightSource[i].spotExponent);
|
||||
intensity *= step(lightSource[i].spotCosCutoff, cosine);
|
||||
}
|
||||
|
||||
/* diffuse light */
|
||||
vec3 light_diffuse = lightSource[i].diffuse.rgb;
|
||||
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
|
||||
L_diffuse += light_diffuse*diffuse_bsdf*intensity;
|
||||
/* falloff */
|
||||
float distance = length(d);
|
||||
|
||||
/* specular light */
|
||||
vec3 light_specular = 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;
|
||||
intensity /= lightSource[i].constantAttenuation +
|
||||
lightSource[i].linearAttenuation * distance +
|
||||
lightSource[i].quadraticAttenuation * distance * distance;
|
||||
}
|
||||
|
||||
/* diffuse light */
|
||||
vec3 light_diffuse = lightSource[i].diffuse.rgb;
|
||||
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
|
||||
L_diffuse += light_diffuse*diffuse_bsdf*intensity;
|
||||
|
||||
/* specular light */
|
||||
vec3 light_specular = 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 /* USE_COLOR_MATERIAL */
|
||||
|
||||
/* Compute diffuse color. */
|
||||
float alpha;
|
||||
if (use_texture_2d) {
|
||||
L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
|
||||
}
|
||||
else {
|
||||
L_diffuse *= diffuse.rgb;
|
||||
}
|
||||
alpha = diffuse.a;
|
||||
#ifdef USE_TEXTURE_2D
|
||||
L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
|
||||
#else
|
||||
L_diffuse *= diffuse.rgb;
|
||||
#endif
|
||||
|
||||
/* Sum lighting. */
|
||||
vec3 L = /*gl_FrontLightModelProduct.sceneColor.rgb +*/ L_diffuse;
|
||||
if (shininess != 0.0f) {
|
||||
L += L_specular * specular.rgb;
|
||||
}
|
||||
vec3 L = L_diffuse + L_specular * specular.rgb;
|
||||
|
||||
/* Write out fragment color. */
|
||||
gl_FragColor = vec4(L, alpha);
|
||||
gl_FragColor = vec4(L, diffuse.a);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -86,8 +86,10 @@ typedef struct Transform {
|
||||
static bool g_use_osd_glsl = false;
|
||||
static int g_active_uv_index = -1;
|
||||
|
||||
static GLuint g_flat_fill_program = 0;
|
||||
static GLuint g_smooth_fill_program = 0;
|
||||
static GLuint g_flat_fill_solid_program = 0;
|
||||
static GLuint g_flat_fill_texture2d_program = 0;
|
||||
static GLuint g_smooth_fill_solid_program = 0;
|
||||
static GLuint g_smooth_fill_texture2d_program = 0;
|
||||
static GLuint g_wireframe_program = 0;
|
||||
|
||||
static GLuint g_lighting_ub = 0;
|
||||
@ -324,15 +326,8 @@ void bindProgram(PartitionedGLMeshInterface * /*mesh*/,
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
|
||||
|
||||
/* Color */
|
||||
GLboolean use_lighting, use_color_material, use_texture_2d;
|
||||
GLboolean use_lighting;
|
||||
glGetBooleanv(GL_LIGHTING, &use_lighting);
|
||||
glGetBooleanv(GL_COLOR_MATERIAL, &use_color_material);
|
||||
glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
|
||||
|
||||
glUniform1i(glGetUniformLocation(program, "use_color_material"),
|
||||
use_color_material);
|
||||
glUniform1i(glGetUniformLocation(program, "use_texture_2d"),
|
||||
use_texture_2d);
|
||||
|
||||
if (use_lighting) {
|
||||
float color[4];
|
||||
@ -376,8 +371,10 @@ void openSubdiv_osdGLDisplayInit(void)
|
||||
{
|
||||
static bool need_init = true;
|
||||
if (need_init) {
|
||||
g_flat_fill_program = linkProgram("#define FLAT_SHADING\n");
|
||||
g_smooth_fill_program = linkProgram("#define SMOOTH_SHADING\n");
|
||||
g_flat_fill_solid_program = linkProgram("#define FLAT_SHADING\n");
|
||||
g_flat_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
|
||||
g_smooth_fill_solid_program = linkProgram("#define SMOOTH_SHADING\n");
|
||||
g_smooth_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
|
||||
g_wireframe_program = linkProgram("#define WIREFRAME\n");
|
||||
|
||||
glGenBuffers(1, &g_lighting_ub);
|
||||
@ -394,11 +391,17 @@ void openSubdiv_osdGLDisplayDeinit(void)
|
||||
if (g_lighting_ub != 0) {
|
||||
glDeleteBuffers(1, &g_lighting_ub);
|
||||
}
|
||||
if (g_flat_fill_program) {
|
||||
glDeleteProgram(g_flat_fill_program);
|
||||
if (g_flat_fill_solid_program) {
|
||||
glDeleteProgram(g_flat_fill_solid_program);
|
||||
}
|
||||
if (g_smooth_fill_program) {
|
||||
glDeleteProgram(g_flat_fill_program);
|
||||
if (g_flat_fill_texture2d_program) {
|
||||
glDeleteProgram(g_flat_fill_texture2d_program);
|
||||
}
|
||||
if (g_smooth_fill_solid_program) {
|
||||
glDeleteProgram(g_flat_fill_solid_program);
|
||||
}
|
||||
if (g_smooth_fill_texture2d_program) {
|
||||
glDeleteProgram(g_smooth_fill_texture2d_program);
|
||||
}
|
||||
if (g_wireframe_program) {
|
||||
glDeleteProgram(g_wireframe_program);
|
||||
@ -505,12 +508,26 @@ static GLuint preapre_patchDraw(PartitionedGLMeshInterface *mesh,
|
||||
return program;
|
||||
}
|
||||
|
||||
program = g_smooth_fill_program;
|
||||
if (fill_quads) {
|
||||
int model;
|
||||
GLboolean use_texture_2d;
|
||||
glGetIntegerv(GL_SHADE_MODEL, &model);
|
||||
glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
|
||||
if (model == GL_FLAT) {
|
||||
program = g_flat_fill_program;
|
||||
if (use_texture_2d) {
|
||||
program = g_flat_fill_texture2d_program;
|
||||
}
|
||||
else {
|
||||
program = g_flat_fill_solid_program;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (use_texture_2d) {
|
||||
program = g_smooth_fill_texture2d_program;
|
||||
}
|
||||
else {
|
||||
program = g_smooth_fill_solid_program;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
Loading…
Reference in New Issue
Block a user