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 float shininess;
|
||||||
|
|
||||||
uniform sampler2D texture_buffer;
|
uniform sampler2D texture_buffer;
|
||||||
uniform bool use_color_material;
|
|
||||||
uniform bool use_texture_2d;
|
|
||||||
|
|
||||||
in block {
|
in block {
|
||||||
VertexData v;
|
VertexData v;
|
||||||
@ -236,99 +234,89 @@ void main()
|
|||||||
vec3 L_diffuse = vec3(0.0);
|
vec3 L_diffuse = vec3(0.0);
|
||||||
vec3 L_specular = vec3(0.0);
|
vec3 L_specular = vec3(0.0);
|
||||||
|
|
||||||
if (use_color_material == false) {
|
#ifndef USE_COLOR_MATERIAL
|
||||||
/* Assume NUM_SOLID_LIGHTS directional lights. */
|
/* Assume NUM_SOLID_LIGHTS directional lights. */
|
||||||
for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
|
for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
|
||||||
vec3 light_direction = lightSource[i].position.xyz;
|
vec4 Plight = lightSource[i].position;
|
||||||
|
#ifdef USE_DIRECTIONAL_LIGHT
|
||||||
/* Diffuse light. */
|
vec3 l = (Plight.w == 0.0)
|
||||||
vec3 light_diffuse = lightSource[i].diffuse.rgb;
|
? normalize(Plight.xyz)
|
||||||
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
|
: normalize(inpt.v.position.xyz);
|
||||||
L_diffuse += light_diffuse * diffuse_bsdf;
|
#else /* USE_DIRECTIONAL_LIGHT */
|
||||||
|
/* TODO(sergey): We can normalize it outside of the shader. */
|
||||||
/* Specular light. */
|
vec3 l = normalize(Plight.xyz);
|
||||||
vec4 Plight = lightSource[i].position;
|
#endif /* USE_DIRECTIONAL_LIGHT */
|
||||||
vec3 l = (Plight.w == 0.0)
|
vec3 h = normalize(l + vec3(0, 0, 1));
|
||||||
? normalize(Plight.xyz) : normalize(Plight.xyz -
|
float d = max(0.0, dot(N, l));
|
||||||
inpt.v.position.xyz);
|
float s = pow(max(0.0, dot(N, h)), 500.0f);
|
||||||
vec3 light_specular = lightSource[i].specular.rgb;
|
L_diffuse += d * lightSource[i].diffuse;
|
||||||
vec3 H = normalize(l + vec3(0,0,1));
|
L_specular += s * lightSource[i].specular;
|
||||||
float specular_bsdf = pow(max(dot(N, H), 0.0),
|
|
||||||
shininess);
|
|
||||||
L_specular += light_specular * specular_bsdf;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
#else /* USE_COLOR_MATERIAL */
|
||||||
vec3 varying_position = inpt.v.position.xyz;
|
vec3 varying_position = inpt.v.position.xyz;
|
||||||
vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
|
vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
|
||||||
normalize(varying_position): vec3(0.0, 0.0, -1.0);
|
normalize(varying_position): vec3(0.0, 0.0, -1.0);
|
||||||
for (int i = 0; i < num_enabled_lights; i++) {
|
for (int i = 0; i < num_enabled_lights; i++) {
|
||||||
/* todo: this is a slow check for disabled lights */
|
/* todo: this is a slow check for disabled lights */
|
||||||
if (lightSource[i].specular.a == 0.0)
|
if (lightSource[i].specular.a == 0.0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
float intensity = 1.0;
|
float intensity = 1.0;
|
||||||
vec3 light_direction;
|
vec3 light_direction;
|
||||||
|
|
||||||
if (lightSource[i].position.w == 0.0) {
|
if (lightSource[i].position.w == 0.0) {
|
||||||
/* directional light */
|
/* directional light */
|
||||||
light_direction = lightSource[i].position.xyz;
|
light_direction = lightSource[i].position.xyz;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* point light */
|
/* point light */
|
||||||
vec3 d = lightSource[i].position.xyz - varying_position;
|
vec3 d = lightSource[i].position.xyz - varying_position;
|
||||||
light_direction = normalize(d);
|
light_direction = normalize(d);
|
||||||
|
|
||||||
/* spot light cone */
|
/* spot light cone */
|
||||||
if (lightSource[i].spotCutoff < 90.0) {
|
if (lightSource[i].spotCutoff < 90.0) {
|
||||||
float cosine = max(dot(light_direction,
|
float cosine = max(dot(light_direction,
|
||||||
-lightSource[i].spotDirection.xyz),
|
-lightSource[i].spotDirection.xyz),
|
||||||
0.0);
|
0.0);
|
||||||
intensity = pow(cosine, lightSource[i].spotExponent);
|
intensity = pow(cosine, lightSource[i].spotExponent);
|
||||||
intensity *= step(lightSource[i].spotCosCutoff, cosine);
|
intensity *= step(lightSource[i].spotCosCutoff, cosine);
|
||||||
}
|
|
||||||
|
|
||||||
/* falloff */
|
|
||||||
float distance = length(d);
|
|
||||||
|
|
||||||
intensity /= lightSource[i].constantAttenuation +
|
|
||||||
lightSource[i].linearAttenuation * distance +
|
|
||||||
lightSource[i].quadraticAttenuation * distance * distance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* diffuse light */
|
/* falloff */
|
||||||
vec3 light_diffuse = lightSource[i].diffuse.rgb;
|
float distance = length(d);
|
||||||
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
|
|
||||||
L_diffuse += light_diffuse*diffuse_bsdf*intensity;
|
|
||||||
|
|
||||||
/* specular light */
|
intensity /= lightSource[i].constantAttenuation +
|
||||||
vec3 light_specular = lightSource[i].specular.rgb;
|
lightSource[i].linearAttenuation * distance +
|
||||||
vec3 H = normalize(light_direction - V);
|
lightSource[i].quadraticAttenuation * distance * distance;
|
||||||
|
|
||||||
float specular_bsdf = pow(max(dot(N, H), 0.0),
|
|
||||||
gl_FrontMaterial.shininess);
|
|
||||||
L_specular += light_specular*specular_bsdf * intensity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
/* Compute diffuse color. */
|
||||||
float alpha;
|
#ifdef USE_TEXTURE_2D
|
||||||
if (use_texture_2d) {
|
L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
|
||||||
L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
|
#else
|
||||||
}
|
L_diffuse *= diffuse.rgb;
|
||||||
else {
|
#endif
|
||||||
L_diffuse *= diffuse.rgb;
|
|
||||||
}
|
|
||||||
alpha = diffuse.a;
|
|
||||||
|
|
||||||
/* Sum lighting. */
|
/* Sum lighting. */
|
||||||
vec3 L = /*gl_FrontLightModelProduct.sceneColor.rgb +*/ L_diffuse;
|
vec3 L = L_diffuse + L_specular * specular.rgb;
|
||||||
if (shininess != 0.0f) {
|
|
||||||
L += L_specular * specular.rgb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write out fragment color. */
|
/* Write out fragment color. */
|
||||||
gl_FragColor = vec4(L, alpha);
|
gl_FragColor = vec4(L, diffuse.a);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +86,10 @@ typedef struct Transform {
|
|||||||
static bool g_use_osd_glsl = false;
|
static bool g_use_osd_glsl = false;
|
||||||
static int g_active_uv_index = -1;
|
static int g_active_uv_index = -1;
|
||||||
|
|
||||||
static GLuint g_flat_fill_program = 0;
|
static GLuint g_flat_fill_solid_program = 0;
|
||||||
static GLuint g_smooth_fill_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_wireframe_program = 0;
|
||||||
|
|
||||||
static GLuint g_lighting_ub = 0;
|
static GLuint g_lighting_ub = 0;
|
||||||
@ -324,15 +326,8 @@ void bindProgram(PartitionedGLMeshInterface * /*mesh*/,
|
|||||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
|
||||||
|
|
||||||
/* Color */
|
/* Color */
|
||||||
GLboolean use_lighting, use_color_material, use_texture_2d;
|
GLboolean use_lighting;
|
||||||
glGetBooleanv(GL_LIGHTING, &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) {
|
if (use_lighting) {
|
||||||
float color[4];
|
float color[4];
|
||||||
@ -376,8 +371,10 @@ void openSubdiv_osdGLDisplayInit(void)
|
|||||||
{
|
{
|
||||||
static bool need_init = true;
|
static bool need_init = true;
|
||||||
if (need_init) {
|
if (need_init) {
|
||||||
g_flat_fill_program = linkProgram("#define FLAT_SHADING\n");
|
g_flat_fill_solid_program = linkProgram("#define FLAT_SHADING\n");
|
||||||
g_smooth_fill_program = linkProgram("#define SMOOTH_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");
|
g_wireframe_program = linkProgram("#define WIREFRAME\n");
|
||||||
|
|
||||||
glGenBuffers(1, &g_lighting_ub);
|
glGenBuffers(1, &g_lighting_ub);
|
||||||
@ -394,11 +391,17 @@ void openSubdiv_osdGLDisplayDeinit(void)
|
|||||||
if (g_lighting_ub != 0) {
|
if (g_lighting_ub != 0) {
|
||||||
glDeleteBuffers(1, &g_lighting_ub);
|
glDeleteBuffers(1, &g_lighting_ub);
|
||||||
}
|
}
|
||||||
if (g_flat_fill_program) {
|
if (g_flat_fill_solid_program) {
|
||||||
glDeleteProgram(g_flat_fill_program);
|
glDeleteProgram(g_flat_fill_solid_program);
|
||||||
}
|
}
|
||||||
if (g_smooth_fill_program) {
|
if (g_flat_fill_texture2d_program) {
|
||||||
glDeleteProgram(g_flat_fill_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) {
|
if (g_wireframe_program) {
|
||||||
glDeleteProgram(g_wireframe_program);
|
glDeleteProgram(g_wireframe_program);
|
||||||
@ -505,12 +508,26 @@ static GLuint preapre_patchDraw(PartitionedGLMeshInterface *mesh,
|
|||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
program = g_smooth_fill_program;
|
|
||||||
if (fill_quads) {
|
if (fill_quads) {
|
||||||
int model;
|
int model;
|
||||||
|
GLboolean use_texture_2d;
|
||||||
glGetIntegerv(GL_SHADE_MODEL, &model);
|
glGetIntegerv(GL_SHADE_MODEL, &model);
|
||||||
|
glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
|
||||||
if (model == GL_FLAT) {
|
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 {
|
else {
|
||||||
|
Loading…
Reference in New Issue
Block a user