渲染世界的OPENGL<10>GLSL编程-着色器统一值

属性是每个顶点位置、表面法线和纹理坐标都需要的,而统一值则用于为整个图元批次向保持不变的着色器传递数据。对于顶点着色器来说,最普遍的统一值就是变换矩阵。任何着色器变量都可以指定为一个统一值,而统一值可以在3个着色器阶段中的任意一个阶段。
创建统一值的方法很简单,只需要在变量声明开始的时候放置一个uniform关键字。
统一值不能标记为in或out,他们也不能在着色器阶段之间进行插值,并且他们总是只读的。

(1)寻找统一值
在一个着色器进行编译和连接之后,我们必须在着色器中统一值位置。

glGetUniformLocation(GLuint shaderID, const GLchar* varName);

注意,这个函数返回一个有符号的整数,代表在shaderID指定的着色器中由varName命名的变量位置。
注意,着色器变量名称是区分大小写的。如果返回值为-1,那么输入的名字就不能被定位。
即使着色器编译正确, 但是如果不是在着色器当中直接使用过,那么一个统一值名称仍然能够在这个着色器当中消失。我们不必担心统一变量会被优化掉,但是如果声明了一个统一值而不去使用,那么编译器会丢掉它。

(2)设置标量和向量的统一值
一个单独的标量和向量数据类型可以再glUniform函数当中使用下面的变量进行设置:

void glUniform4f(GLint location, GLfloat v0, GLfloat v1,GLfloat v2,GLfloat v3)

其他数量以及不同的数据类型类似上面的函数,第一位为location。

GLint locTime;
locTime=glGetUniformLocation(myShader, "fTime");


glUseProgram(myShader);
glUniform1f(locTime, 42.5f);

注意上面的执行顺序,其他数据类型大同小异:首先声明变量,使用变量得到对应统一值的location,然后选定着色器激活程序,最后赋值。

(3)设置统一数组
注意这种赋值和上面的赋值是完全不同的两回事。
glUnform函数还接受一个指针,假定指向一个数值数组。

void glUniform4fv(GLint location, GLuint count, GLfloat* v);

void glUniform4iv(GLint location, GLuint couunt, GLint* v);

在这里,count值代表每个含有x分量的数组中有多少个元素,其中x是位于函数名字末尾的数字。
关于函数的赋值的目标数,请注意函数末尾的几个字母。
注意:可以一次性赋值一个向量,那么count就为1啦。

(4)设置统一矩阵

设置矩阵统一值,着色器矩阵数据类型只有浮点类型,这样变量就少了很多。

glUniformMatrix2fv(GLint location, GLuint count, GLboolean transpose, const GLfloat *m);
glUniformMatrix3fv(GLint location, GLuint count, GLboolean transpose, const GLfloat *m);
glUniformMatrix4fv(GLint location, GLuint count, GLboolean transpose, const GLfloat *m);

变量count代表指针参数m中存储的矩阵数量(可以使用矩阵数组!)。如果矩阵已经按照列优先排列进行存储,布尔值标记transpose将会被设置为GL_TRUE。将这个值设置为GL_FALSE会导致这个矩阵复制到着色器当中的时发生变换。
如果使用一个行优先矩阵布局(Direct3D),那么这一点就要考虑进去。

(5)平面着色器

// Flat Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

// 注意这个透视投影矩阵
uniform mat4    mvpMatrix;

// 传入的顶点信息
in vec4 vVertex;

void main(void) 
    { 
    //这是对几何图形进行变换的操作
    gl_Position = mvpMatrix * vVertex;
    }

这个是顶点渲染器,作为vp文件存放在程序的主目录中。

// Flat Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

// 设置几何图形为实体。
uniform vec4 vColorValue;

// 输出片段颜色
out vec4 vFragColor;


void main(void)
   { 
   vFragColor = vColorValue;
   }

存储在fp文件,在主程序工程文件目录下,等待读取。



#pragma comment(lib,"GLTools.lib")
#include <GLTools.h>    // OpenGL toolkit
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <StopWatch.h>
#include <GL/glut.h>




GLFrame             viewFrame;
GLFrustum           viewFrustum;
GLTriangleBatch     torusBatch;
GLMatrixStack       modelViewMatrix;
GLMatrixStack       projectionMatrix;
GLGeometryTransform transformPipeline;

GLuint  flatShader;         // The Flat shader

GLint   locMVP;             // 重点:声明访问到shader程序当中的统一值
GLint   locColor;           // 重点:声明访问到shader程序当中的统一值



                            // 渲染环境初始化
void SetupRC(void)
{
    // Background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glEnable(GL_DEPTH_TEST);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    viewFrame.MoveForward(4.0f);

    // Make the torus
    gltMakeTorus(torusBatch, .80f, 0.25f, 52, 26);

    //加载shader程序
    flatShader = gltLoadShaderPairWithAttributes("FlatShader.vp", "FlatShader.fp", 1, GLT_ATTRIBUTE_VERTEX, "vVertex");

    //在SetUpRC当中加载对应shader当中的统一值属性。
    locMVP = glGetUniformLocation(flatShader, "mvpMatrix");
    locColor = glGetUniformLocation(flatShader, "vColorValue");
}

// Cleanup
void ShutdownRC(void)
{

}


// Called to draw scene
void RenderScene(void)
{
    static CStopWatch rotTimer;

    // Clear the window and the depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    modelViewMatrix.PushMatrix(viewFrame);
    modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f, 1.0f, 0.0f);

    GLfloat vColor[] = { 0.1f, 0.1f, 1.f, 1.0f };

    //注意,在SetupRC当中装载并且得到对应shader当中的统一值
    //在Render当中对shader程序进行加载,并且对统一值进行赋值。
    glUseProgram(flatShader);
    glUniform4fv(locColor, 1, vColor);
    glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
    torusBatch.Draw();

    modelViewMatrix.PopMatrix();


    glutSwapBuffers();
    glutPostRedisplay();
}



void ChangeSize(int w, int h)
{
    // Prevent a divide by zero
    if (h == 0)
        h = 1;

    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);

    viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 100.0f);
    //得到透视投影矩阵
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}

///////////////////////////////////////////////////////////////////////////////
// Main entry point for GLUT based programs
int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Simple Transformed Geometry");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);

    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    SetupRC();
    glutMainLoop();
    ShutdownRC();
    return 0;
}

对平面着色器进行使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值