This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
Alexander Romanov d969192fbe Wide lines + line stipple deprecated API replacement
The patch contains an implementation of the wide lines and the line stipple that is necessary for OpenGL upgrade.

For the implementation I have chosen the geometry shader because it required minimum changes for the wrapper calls and such implementation is the best for the "basic shader" architecture.

There are few shortcomings that can be corrected in future. They all are related to the fact that the lines in one strip are not connected with each other. So the stipple pattern is not continuous on the common vertex of two lines. There is also no continuity of form (each line is an independent rectangular).
But the advantage is that even outdated glBegin, glVertex work! Though with the above restrictions.
Continuity of form and stipple can be implemented with additional attributes, and it will require more changes in calls.

At the moment, the patch replaces calls for some "gestures". It works satisfactorily for "cross" or "rectangular" and not so good for "lasso" and "circle" due to the above-mentioned shortcomings.

Don't forget to set USE_GLSL to true for testing.

Alexander Romanov (Blend4Web Team)

Reviewers: merwin, brecht

Reviewed By: merwin, brecht

Subscribers: aligorith, Evgeny_Rodygin, AlexKowel, yurikovelenov

Differential Revision: https://developer.blender.org/D1880
2016-04-08 10:58:40 +03:00

274 lines
8.3 KiB
GLSL

/* 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
/* Keep these in sync with GPU_basic_shader.h */
#define STIPPLE_HALFTONE 0
#define STIPPLE_QUARTTONE 1
#define STIPPLE_CHECKER_8PX 2
#define STIPPLE_HEXAGON 3
#define STIPPLE_DIAG_STRIPES 4
#define STIPPLE_DIAG_STRIPES_SWAP 5
#define STIPPLE_S3D_INTERLACE_ROW 6
#define STIPPLE_S3D_INTERLACE_ROW_SWAP 7
#define STIPPLE_S3D_INTERLACE_COLUMN 8
#define STIPPLE_S3D_INTERLACE_COLUMN_SWAP 9
#define STIPPLE_S3D_INTERLACE_CHECKERBOARD 10
#define STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP 11
#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
#ifdef USE_STIPPLE
uniform int stipple_id;
#if defined(DRAW_LINE)
varying in float t;
uniform int stipple_pattern;
#endif
#endif
void main()
{
#if defined(USE_STIPPLE)
#if defined(DRAW_LINE)
/* GLSL 1.3 */
if (!bool((1 << int(mod(t, 16))) & stipple_pattern))
discard;
#else
/* We have to use mod function and integer casting.
* This can be optimized further with the bitwise operations
* when GLSL 1.3 is supported. */
if (stipple_id == STIPPLE_HALFTONE ||
stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD ||
stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP)
{
int result = int(mod(gl_FragCoord.x + gl_FragCoord.y, 2));
bool dis = result == 0;
if (stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP)
dis = !dis;
if (dis)
discard;
}
else if (stipple_id == STIPPLE_QUARTTONE) {
int mody = int(mod(gl_FragCoord.y, 4));
int modx = int(mod(gl_FragCoord.x, 4));
if (mody == 0) {
if (modx != 2)
discard;
}
else if (mody == 2){
if (modx != 0)
discard;
}
else
discard;
}
else if (stipple_id == STIPPLE_CHECKER_8PX) {
int result = int(mod(int(gl_FragCoord.x)/8 + int(gl_FragCoord.y)/8, 2));
if (result != 0)
discard;
}
else if (stipple_id == STIPPLE_DIAG_STRIPES) {
int mody = int(mod(gl_FragCoord.y, 16));
int modx = int(mod(gl_FragCoord.x, 16));
if ((16 - modx > mody && mody > 8 - modx) || mody > 24 - modx)
discard;
}
else if (stipple_id == STIPPLE_DIAG_STRIPES_SWAP) {
int mody = int(mod(gl_FragCoord.y, 16));
int modx = int(mod(gl_FragCoord.x, 16));
if (!((16 - modx > mody && mody > 8 - modx) || mody > 24 - modx))
discard;
}
else if (stipple_id == STIPPLE_S3D_INTERLACE_ROW || stipple_id == STIPPLE_S3D_INTERLACE_ROW_SWAP) {
int result = int(mod(gl_FragCoord.y, 2));
bool dis = result == 0;
if (stipple_id == STIPPLE_S3D_INTERLACE_ROW_SWAP)
dis = !dis;
if (dis)
discard;
}
else if (stipple_id == STIPPLE_S3D_INTERLACE_COLUMN || stipple_id == STIPPLE_S3D_INTERLACE_COLUMN_SWAP) {
int result = int(mod(gl_FragCoord.x, 2));
bool dis = result != 0;
if (stipple_id == STIPPLE_S3D_INTERLACE_COLUMN_SWAP)
dis = !dis;
if (dis)
discard;
}
else if (stipple_id == STIPPLE_HEXAGON) {
int mody = int(mod(gl_FragCoord.y, 2));
int modx = int(mod(gl_FragCoord.x, 4));
if (mody != 0) {
if (modx != 1)
discard;
}
else {
if (modx != 3)
discard;
}
}
#endif /* !DRAW_LINE */
#endif /* USE_STIPPLE */
#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
}