OpenGL ES3.0 《学习笔记 八》Vertex Shaders

来源:互联网 发布:飘零网络验证系统源码 编辑:程序博客网 时间:2024/05/22 11:06



Vertex Shader Built-In Variables

1.Built-In Special Variables
gl_VertexID

gl_InstanceID

gl_Position

gl_PointSize

gl_FrontFacing

2.Built-In Uniform State
gl_DepthRange : 

struct gl_DepthRangeParameters
{
highp float near; // near Z
highp float far; // far Z
highp float diff; // far – near
}
uniform gl_DepthRangeParameters gl_DepthRange;

3.Built-In Constants
const mediump int gl_MaxVertexAttribs = 16;

const mediump int gl_MaxVertexUniformVectors = 256;

const mediump int gl_MaxVertexOutputVectors = 16;

const mediump int gl_MaxVertexTextureImageUnits = 16;

const mediump int gl_MaxCombinedTextureImageUnits = 32;

查询:

glGetIntegerv ( GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs );
glGetIntegerv ( GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniforms );
glGetIntegerv ( GL_MAX_VARYING_VECTORS, &maxVaryings );
glGetIntegerv ( GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureUnits );
glGetIntegerv ( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedTextureUnits );


Precision Qualifiers

三种精度:

(1)lowp

(2)mediump

(3)highp

定义默认精度,如:

precision highp float;

precision mediump int;

如果没有定义默认精度,则 int 和 float 的默认精度都是 highp


Number of Uniforms Limitations in a Vertex Shader

gl_MaxVertexUniformVectors

一般来说常数是参与计数的,所以下面两段同样逻辑的vertex shader,后者优于前者 :

《《《《《《《《《《《《《《《《《《《《《《《《

#version 300 es
#define NUM_TEXTURES 2

uniform mat4 tex_matrix[NUM_TEXTURES];
uniform bool enable_tex[NUM_TEXTURES];
uniform bool enable_tex_matrix[NUM_TEXTURES];

in vec4 a_texcoord0;
in vec4 a_texcoord1;
out vec4 v_texcoord[NUM_TEXTURES];

void main {
v_texcoord[0] = vec4(0.0, 0.0, 0.0, 0.0);
if(enable_tex[0]) {
if(enable_tex_matrix[0]) {
v_texcoord[0] = tex_matrix[0] * a_texcoord0;
} else {
v_texcoord[0] = a_texcoord0;
}


v_texcoord[1] = vec4(0.0, 0.0, 0.0, 0.0);
if(enable_tex[1]) {
if(enable_tex_matrix[1]) {
v_texcoord[1] = tex_matrix[1] * a_texcoord1;
} else {
v_texcoord[1] = a_texcoord1;
}
}

// set gl_Position
}

《《《《《《《《《《《《《《《《《《《《《《《《


《《《《《《《《《《《《《《《《《《《《《《《《

#version 300 es
#define NUM_TEXTURES 2

const int c_zero = 0;
const int c_one = 1;

uniform mat4 tex_matrix[NUM_TEXTURES];
uniform bool enable_tex[NUM_TEXTURES];
uniform bool enable_tex_matrix[NUM_TEXTURES];

in vec4 a_texcoord0; 
in vec4 a_texcoordl;
out vec4 v_texcoord[NUM_TEXTURES];

void main() {
v_texcoord[c_zero] = vec4 (float(c_zero), float(c_zero), float(c_zero), float(c_one));
if(enable_tex[c_zero]) {
if ( enable_tex_matrix[c_zero] ) {
v_texcoord[c_zero] = tex_matrix[c_zero] * a_texcoord0;
} else {
v_texcoord[c_zero] = a_texcoord0;
}
}

v_texcoord[c_one] = vec4(float(c_zero), float(c_zero), float(c_zero), float(c_one));
if(enable_tex[c_one]) {
if(enable_tex_matrix[c_one]) {
v_texcoord[c_one] = tex_matrix[c_one] * a_texcoordl;
} else {
v_texcoord[c_one] = a_texcoordl;
}
}

// set gl_Position to make this into a valid vertex shader
}

《《《《《《《《《《《《《《《《《《《《《《《《


Vertex Shader Examples

• Transforming vertex position with a matrix

• Lighting computations to generate per-vertex diffuse and specular color

• Texture coordinate generation

• Vertex skinning

• Displacing vertex position with a texture lookup value

1.Matrix Transformations

《《《《《《《《《《《《《《《《《《《《《《《《
#version 300 es

uniform mat4 u_mvpMatrix; // matrix to convert position from model space to clip space

layout(location = 0) in vec4 a_position;
layout(location = 1) in vec4 a_color;

out vec4 v_color;

void main() {
v_color = a_color;
gl_Position = u_mvpMatrix * a_position;
}

《《《《《《《《《《《《《《《《《《《《《《《《 


model–view–projection (MVP) matrix : u_mvpMatrix

The MVP matrix is the product of three very important transformation matrices in 3D graphics that perform this transformation: the model matrix, the view matrix, and the projection matrix.

The transformations performed by each of the individual matrices that make up the MVP matrix are as follows:

• Model matrix—Transform object coordinates to world coordinates.

• View matrix—Transform world coordinates to eye coordinates.

• Projection matrix—Transform eye coordinates to clip coordinates.


Model–View Matrix : 

In fixed-function OpenGL, the model–view matrix can be created using functions such as glRotatef, glTranslatef, and glScalef. Because these functions do not exist 

in OpenGL ES 2.0 or 3.0, it is up to the application to handle creation of the model–view matrix.


Projection Matrix : 

In fixed-function OpenGL, this transformation was specified using glFrustumor the OpenGL utility function gluPerspective. 


将 MVP matrix 加载到vertex shader :

The MVP matrix is loaded into the uniform for the shader using glUniformMatrix4fv.

// Get the uniform locations
userData->mvpLoc =
glGetUniformLocation  (  userData->programObject,
"u_mvpMatrix" );

// Load the MVP matrix
glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE,
(GLfloat*) &userData->mvpMatrix.m[0][0] ); 


Lighting in a Vertex Shader

1.平行光(光源在无限远处),观察者在无限远处


Plight is the position of the light (Plight. w= 0), N is the normal, and H is the half-plane vector. Because Plight. w= 0, the light direction vector will be P light. xyz. The half-plane vector H is computed as ||VPlight + VPeye||. As both the light source and viewer are at infinity, the half-plane vector H =||Plight. xyz+ (0, 0, l)||.


<directional_light>

• direction —The normalized light direction in eye space.
• halfplane —The normalized half-plane vector H. This can be precomputed for a directional light, as it does not change.
• ambient_color —The ambient color of the light.
• diffuse_color —The diffuse color of the light.
• specular_color —The specular color of the light.


 <material_properties>

• ambient_color—The ambient color of the material.
• diffuse_color—The diffuse color of the material.
• specular_color—The specular color of the material.
• specular_exponent—The specular exponent that describes the shininess of the material and is used to control the shininess of the specular highlight.


Directional Light Vertex shader 示例:

注:公式可以参考红宝书第七版 P148。

#version 300 es

struct directional_light {
vec3 direction; // normalized light direction in eye
vec3 halfplane; // normalized half-plane vector
vec4 ambient_color;
vec4 diffuse_color;
vec4 specular_color;
};
struct material_properties {
vec4 ambient_color;
vec4 diffuse_color;
vec4 specular_color;
float specular_exponent;
};

const float c_zero = 0.0;
const float c_one = 1.0;

uniform material_properties material;
uniform directional_light light;

// normal has been transformed into eye space and is a
// normalized vector; this function returns the computed color
vec4 directional_light_color (vec3 normal) {
vec4 computed_color = vec4(c_zero, c_zero, c_zero, c_zero);
float ndotl; // dot product of normal & light direction
float ndoth; // dot product of normal & half-plane vector
ndotl = max(c_zero, dot(normal, light.direction));
ndoth = max(c_zero, dot(normal, light.halfplane));
computed_color += (light.ambient_color * material.ambient_color );
computed_color += (ndotl * light.diffuse_color * material.diffuse_color );
if(ndoth > c_zero) {
computed_color += (pow(ndoth, material.specular_exponent) * material.specular_color * light.specular_color);
}
return computed_color;
}
// add a main function to make this into a valid vertex shader


2.点光源



点光源距离衰减公式:



<spot_light>

• direction —The light direction in eye space.
• ambient_color —The ambient color of the light.
• diffuse_color —The diffuse color of the light.
• specular_color —The specular color of the light.
• attenuation_factors —The distance attenuation factors K0, K1, and K2.
• compute_distance_attenuation —A boolean term that determines whether the distance attenuation must be computed.
• spot_direction —The normalized spot direction vector.
• spot_exponent —The spotlight exponent used to compute the spot cutoff factor.
• spot_cutoff_angle —The spotlight cutoff angle in degrees.


Spotlight vertex shader 示例:

#version 300 es
struct spot_light {
vec4 position; // light position in eye space
vec4 ambient_color;
vec4 diffuse_color;
vec4 specular_color;
vec3 spot_direction; // normalized spot direction
vec3 attenuation_factors; // attenuation factors K0, K1, K2
bool compute_distance_attenuation;
float spot_exponent; // spotlight exponent term
float spot_cutoff_angle; // spot cutoff angle in degrees
};
struct material_properties {
vec4 ambient_color;
vec4 diffuse_color;
vec4 specular_color;
float specular_exponent;
};

const float c_zero = 0.0;
const float c_one = 1.0;

uniform material_properties material;
uniform spot_light light;

// normal and position are normal and position values in eye space.
// normal is a normalized vector.
// This function returns the computed color.
vec4 spot_light_color(vec3 normal, vec4 position) {
vec4 computed_color = vec4(c_zero, c_zero, c_zero, c_zero);
vec3 lightdir;
vec3 halfplane;
float ndotl, ndoth;
float att_factor;
att_factor = c_one;
// we assume "w" values for light position and vertex position are the same
lightdir = light.position.xyz - position.xyz;
// compute distance attenuation
if(light.compute_distance_attenuation) {
vec3 att_dist;
att_dist.x = c_one;
att_dist.z = dot(lightdir, lightdir);
att_dist.y = sqrt(att_dist.z);
att_factor = c_one/dot(att_dist, light.attenuation_factors);
}
// normalize the light direction vector
lightdir = normalize(lightdir);
// compute spot cutoff factor
if(light.spot_cutoff_angle < 180.0) {
float spot_factor = dot(-lightdir, light.spot_direction);
if(spot_factor >= cos(radians(light.spot_cutoff_angle))) {
spot_factor = pow(spot_factor, light.spot_exponent);
} else {
spot_factor = c_zero;
}
// compute combined distance and spot attenuation factor
att_factor *= spot_factor;
}
if(att_factor > c_zero) {
// process lighting equation --> compute the light color
computed_color += (light.ambient_color * material.ambient_color);
ndotl = max(c_zero, dot(normal, lightdir));
computed_color += (ndotl * light.diffuse_color * material.diffuse_color);
halfplane = normalize(lightdir + vec3(c_zero, c_zero, c_one));
ndoth = dot(normal, halfplane);
if(ndoth > c_zero) {
computed_color += (pow(ndoth, material.specular_exponent) 
* material.specular_color * light.specular_color);
}
// multiply color with computed attenuation
computed_color *= att_factor;
}
return computed_color;
}
// add a main function to make this into a valid vertex shader



Generating Texture Coordinates


Vertex Skinning
The mathematics of vertex skinning is given by the following equations:



 Vertex Skinning Shader with with Checks of Whether Matrix Weight = 0 示例(自己重写了):

#version 300 es
#define NUM_MATRICES 32 // 32 matrices in matrix palette
const int c_zero = 0;
const int c_one = 1;
const int c_two = 2;
const int c_three = 3;
// store 32 4 x 3 matrices as an array of floats representing
// each matrix in row-major order (i.e., 3 vec4s)
uniform vec4 matrix_palette[NUM_MATRICES * 3];
// vertex position and normal attributes
in vec4 a_position;
in vec3 a_normal;
// matrix weights - 4 entries / vertex
in vec4 a_matrixweights;
// matrix palette indices
in vec4 a_matrixindices;

void skin_position(in vec4 position, float m_wt, int m_indx, out vec4 skinned_position) {
vec4 tmp;
tmp.x = dot ( position, matrix_palette[m_indx] );
tmp.y = dot ( position, matrix_palette[m_indx + c_one] );
tmp.z = dot ( position, matrix_palette[m_indx + c_two] );
tmp.w = position.w;
skinned_position += m_wt * tmp;
}

void skin_normal(in vec3 normal, float m_wt, int m_indx,inout vec3 skinned_normal) {
vec3 tmp;
tmp.x = dot ( normal, matrix_palette[m_indx].xyz );
tmp.y = dot ( normal, matrix_palette[m_indx + c_one].xyz );
tmp.z = dot ( normal, matrix_palette[m_indx + c_two].xyz );
skinned_normal += m_wt * tmp;
}

void do_skinning(in vec4 position, in vec3 normal, out vec4 skinned_position, out vec3 skinned_normal) {
skinned_position = vec4(float(c_zero));
skinned_normal = vec3(float(c_zero));
// transform position and normal to eye space using matrix
// palette with four matrices used to transform a vertex
for(int index; index <= c_three; index ++) {
float m_wt = a_matrixweights[index];
int m_indx = int (a_matrixindices[index]) * c_three;

if(m_wt > c_zero) {
skin_position( position, m_wt, m_indx, skinned_position);
skin_normal( normal, m_wt, m_indx, skinned_normal);
}

}
}

// add a main function to make this into a valid vertex shader



Transform Feedback
The 


Vertex Textures
OpenGL ES 3.0 supports texture lookup operations in a vertex shader. This is useful to implement techniques such as displacement mapping, where you can displace the vertex position along the vertex normal based on the texture lookup value in the vertex shader. A typical application of the displacement mapping technique is for rendering terrain or water surfaces.

Performing texture lookup in a vertex shader has some notable limitations:

• The level of detail is not implicitly computed.
• The bias parameter in the texturelookup function is not accepted.
• The base texture is used for mipmapped texture.


The maximum number of texture image units supported by an implementation can be queried using glGetIntegervwith GL_MAX_VERTEX_TEXTURE_UNITS. The minimum number that an OpenGL ES 3.0 implementation can support is 16.


Displacement Mapping Vertex Shader 示例:

#version 300 es
// uniforms used by the vertex shader
uniform mat4 u_mvpMatrix; // matrix to convert P from
// model space to clip space
uniform sampler2D displacementMap;
// attribute inputs to the vertex shader
layout(location = 0) in vec4 a_position; // input position value
layout(location = 1) in vec3 a_normal; // input normal value
layout(location = 2) in vec2 a_texcoord; // input texcoord value
layout(location = 3) in vec4 a_color; // input color
// vertex shader output, input to the fragment shader
out vec4 v_color;


void main ( ) {
v_color = a_color;
float displacement = texture ( displacementMap, a_texcoord ).a;
vec4 displaced_position = a_position + vec4 ( a_normal * displacement, 0.0 );
gl_Position = u_mvpMatrix * displaced_position;
}


OpenGL ES 1.1 Vertex Pipeline as an ES 3.0 Vertex Shader
We 

0 0
原创粉丝点击