Vulkan

II. Positioning---Chapter 3----More Power to the Shaders

More Power to the Shaders

It's all well and good that we are no longer having to transform vertices manually. But perhaps we can move more things to the vertex shader. Could it be possible to move all of ComputePositionOffsets to the vertex shader?

Well, no. The call to glutGet(GL_ELAPSED_TIME) cannot be moved there, since GLSL code cannot directly call C/C++ functions. But everything else can be moved. This is what vertCalcOffset.cpp does.

因为GLSL不能直接调用C/C++函数,glutGet(GL_ELAPSED_TIME)不能调用.但其他都能移动到shader中.

The vertex program is found in data\calcOffset.vert.

Example 3.6. Offset Computing Vertex Shader

#version 330

layout(location = 0) in vec4 position;
uniform float loopDuration;
uniform float time;

void main()
{
    float timeScale = 3.14159f * 2.0f / loopDuration;
    
    float currTime = mod(time, loopDuration);
    vec4 totalOffset = vec4(
        cos(currTime * timeScale) * 0.5f,
        sin(currTime * timeScale) * 0.5f,
        0.0f,
        0.0f);
    
    gl_Position = position + totalOffset;
}

This shader takes two uniforms: the duration of the loop and the elapsed time.

shader有两个unifors:loop的duration和elapsed time.

In this shader, we use a number of standard GLSL functions, like modcos, and sin. We saw mix in the last tutorial. And these are just the tip of the iceberg; there are a lot of standard GLSL functions available.

shader中,我们使用一系列标准GLSL函数,像mod(),cos(),sin().前文中我们看到了mix().这些只是冰山一角,有许多标准GLSL函数.

The rendering code looks quite similar to the previous rendering code:

Example 3.7. Rendering with Time

void display()
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    glUseProgram(theProgram);
    
    glUniform1f(elapsedTimeUniform, glutGet(GLUT_ELAPSED_TIME) / 1000.0f);
    
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
    
    glDrawArrays(GL_TRIANGLES, 0, 3);
    
    glDisableVertexAttribArray(0);
    glUseProgram(0);
    
    glutSwapBuffers();
    glutPostRedisplay();
}

This time, we do not need any code to use the elapsed time; we simply pass it unmodified to the shader.

这次我们不需要使用elapsed time;我们不改变它,简单的将其传送给shader.

You may be wondering exactly how it is that the loopDuration uniform gets set. This is done in our shader initialization routine, and it is done only once:

也许你会想知道uniform变量 loopDuration 怎样get set的.这是在shader初始化程序中进行的,只进行一次:

Example 3.8. Loop Duration Setting

void InitializeProgram()
{
    std::vector<GLuint> shaderList;
    
    shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, "calcOffset.vert"));
    shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, "standard.frag"));
    
    theProgram = Framework::CreateProgram(shaderList);
    
    elapsedTimeUniform = glGetUniformLocation(theProgram, "time");
    
    GLuint loopDurationUnf = glGetUniformLocation(theProgram, "loopDuration");
    glUseProgram(theProgram);
    glUniform1f(loopDurationUnf, 5.0f);
    glUseProgram(0);
}

We get the time uniform as normal with glGetUniformLocation. For the loop duration, we get that in a local variable. Then we immediately set the current program object, set the uniform to a value, and then unset the current program object.

我们使用glGetUniformLocation()获得uniform变量time.对于loopduration变量,我们使用一个局部变量来获得它的值.然后我们立即设置当前program object,设置uniform的值,然后unset当前program object.

Program objects, like all objects that contain internal state, will retain their state unless you explicitly change it. So the value ofloopDuration will be 5.0f in perpetuity; we do not need to set it every frame.

program object像内部state包含的其他object一样,将会保持他们的state除非你确实改变它.所以loopDuration会一直为5.0;我们不需要每一个帧都设置它.


posted on 2012-11-18 19:42  Vulkan  阅读(125)  评论(0编辑  收藏  举报

导航