从着色器访问纹理贴图是非常简单的。纹理坐标将会作为属性传递到我们的顶点着色器,在片段着色器当中,这些属性通常是在顶点之间进行平滑插值的。片段着色器使用这些差值纹理坐标来对纹理进行采样。

(1)只处理纹理单元

// The TexturedIdentity Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
//最为简单的纹理渲染器
#version 130
//传递到顶点着色器当中一个顶点坐标
in vec4 vVertex;
//传递到顶点着色器当中一个纹理坐标,注意核心部分就是这个s和t纹理坐标的输入
//顶点属性vTexCoords以及输出变量vVaringTexCoords。用纹理坐标在三角形表面进行差值
//所需要的,就是这些
in vec2 vTexCoords;smooth out vec2 vVaryingTexCoords;void main(void) { vVaryingTexCoords = vTexCoords;gl_Position = vVertex;}

以上就是仅仅处理纹理单元的顶点着色器,在顶点着色器当中,仅仅对顶点坐标以及顶点的纹理坐标s、t进行相应的传递以及处理。因为其为2D纹理图像,所以纹理坐标仅仅包含s、t。

// The TexturedIdentity Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130//注意这个新的数据变量类型sample2D
//一个采样器(sample)实际上就是一个这么好设计(使用glUniform1i来设置值)它代表我们将要
//采样的纹理所绑定的纹理单元。sample2D中的2D表示这是一个2D纹理,我们也可以使用1D
//2D或者3D等类型的采样器。 这个值总是设置为0,代表指示纹理单元0。
uniform sampler2D colorMap;out vec4 vFragColor;
smooth in vec2 vVaryingTexCoords;void main(void){ //将当前传递进片段着色器当中的st纹理坐标和colormap采样进行texture函数//从而得到最终要进行光栅化的片段颜色。vFragColor = texture(colorMap, vVaryingTexCoords.st);}

如上就是纹理坐标的片段着色器,其中仅仅使用了一个texture函数作为fragColor的值。


#pragma comment(lib,"GLTools.lib")#include <GLTools.h>            // OpenGL toolkit
#include <GLShaderManager.h>    // Shader Manager Class
#include <GL/glut.h>            // Windows FreeGlut equivalentGLBatch triangleBatch;
GLShaderManager shaderManager;GLint   myTexturedIdentityShader;
GLuint  textureID;///////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
{glViewport(0, 0, w, h);
}// 加载一个tga图像作为一个2D纹理,并且进行必要的初始化
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{GLbyte *pBits;int nWidth, nHeight, nComponents;GLenum eFormat;// 读取对应文件当下的图像pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);if (pBits == NULL)return false;//设置对应图象的功能以及设置环绕模式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);glPixelStorei(GL_UNPACK_ALIGNMENT, 1);glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,eFormat, GL_UNSIGNED_BYTE, pBits);//在设置完成参数之后,可以释放对应的字符指针free(pBits);if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||minFilter == GL_LINEAR_MIPMAP_NEAREST ||minFilter == GL_NEAREST_MIPMAP_LINEAR ||minFilter == GL_NEAREST_MIPMAP_NEAREST)//生成对应的2维图像glGenerateMipmap(GL_TEXTURE_2D);return true;
}///////////////////////////////////////////////////////////////////////////////
// 设置渲染环境
void SetupRC()
{// 背景glClearColor(0.0f, 0.0f, 0.0f, 1.0f);//渲染器初始化shaderManager.InitializeStockShaders();// Load up a triangleGLfloat vVerts[] = { -0.5f, 0.0f, 0.0f,0.5f, 0.0f, 0.0f,0.0f, 0.5f, 0.0f };GLfloat vTexCoords[] = { 0.0f, 0.0f,1.0f, 0.0f,0.5f, 1.0f };triangleBatch.Begin(GL_TRIANGLES, 3, 1);triangleBatch.CopyVertexData3f(vVerts);triangleBatch.CopyTexCoordData2f(vTexCoords, 0);triangleBatch.End();//创建对应的着色器myTexturedIdentityShader = gltLoadShaderPairWithAttributes("TexturedIdentity.vp", "TexturedIdentity.fp", 2,GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_TEXTURE0, "vTexCoords");//生成纹理glGenTextures(1, &textureID);//绑定个纹理glBindTexture(GL_TEXTURE_2D, textureID);//对GL_TEXTURE_2D的图像进行加载LoadTGATexture("stone.tga", GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
}///////////////////////////////////////////////////////////////////////////////
// Cleanup
void ShutdownRC()
{glDeleteProgram(myTexturedIdentityShader);glDeleteTextures(1, &textureID);
}///////////////////////////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{// 清除缓冲区的数据glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);//产生纹理渲染器glUseProgram(myTexturedIdentityShader);glBindTexture(GL_TEXTURE_2D, textureID);//再次绑定//设置渲染器程序当中的colormapGLint iTextureUniform = glGetUniformLocation(myTexturedIdentityShader, "colorMap");glUniform1i(iTextureUniform, 0);//设置为0,因为是第一张图 triangleBatch.Draw();// Perform the buffer swap to display back bufferglutSwapBuffers();
}///////////////////////////////////////////////////////////////////////////////
// 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("Textured Triangle");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;
}

最终的调用主程序,注意其中对纹理的调用和绑定。

(2)照亮纹理单元
在所有的光照着色器当中,我们实际上是将基本色值和光线的强度相乘,这可以是逐个顶点进行的,也可以是逐个像素进行的。
我们将修改过的ADSPhong着色器称为ADSTexture
会对纹理进行采样,然后用纹理的颜色值乘以光线强度。
正常来说,如果环境刚和漫反射的和可能会很亮,以至于看起来就是纯白色,可是如果乘以一个纹理颜色,那么结果就会是一个和原来纹理一样亮度的纹理颜色。看起来没什么不对,但是:
注意,在光照计算的时候,每个颜色通道的值通常是大于1的,意味着只收使得颜色过于饱和以及获得一个白色镜面高光是可能的,不过正确的方法应该是将环境光和漫反射光强度的和和纹理颜色相乘,最后加上镜面光的部分。

// ADS Point lighting Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130// 输入每一个顶点以及法线向量
in vec4 vVertex;
in vec3 vNormal;
in vec4 vTexture0;uniform mat4   mvpMatrix;
uniform mat4   mvMatrix;
uniform mat3   normalMatrix;
uniform vec3   vLightPosition;// 仍然是ADSPhong 的套路,法线插值,把计算的重心转移到片段着色器
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
smooth out vec2 vTexCoords;void main(void) { // 计算视觉坐标系当中的法向量vVaryingNormal = normalMatrix * vNormal;// 视觉坐标当中的顶点vec4 vPosition4 = mvMatrix * vVertex;vec3 vPosition3 = vPosition4.xyz / vPosition4.w;// 得到光的方向vVaryingLightDir = normalize(vLightPosition - vPosition3);// 传递贴图坐标vTexCoords = vTexture0.st;// 最后把变换应用到几何坐标上gl_Position = mvpMatrix * vVertex;}

顶点渲染器程序代码,vp文件。其中处理了视觉坐标系下的法向量、光照方向、以及传递贴图坐标。

// ADS Point lighting Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130
//片段颜色
out vec4 vFragColor;//得到三种光照颜色的统一值
uniform vec4      ambientColor;
uniform vec4      diffuseColor;
uniform vec4      specularColor;
uniform sampler2D colorMap;//以及纹理取样//输入的视觉坐标系当中的顶点法线向量
//光线向量
//纹理坐标
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
smooth in vec2 vTexCoords;void main(void){ // 点乘得到漫反射光照强度float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));// 光强乘以漫反射颜色,alpha通道默认为1vFragColor = diff * diffuseColor;// 在此基础上加上环境光颜色vFragColor += ambientColor;// 将片段颜色和纹理进行乘运算vFragColor *= texture(colorMap, vTexCoords);// 最后进行镜面光vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));if(diff != 0) {float fSpec = pow(spec, 128.0);vFragColor.rgb += vec3(fSpec, fSpec, fSpec);}}

在frag渲染器当中,注意,其渲染顺序,首先是漫反射和环境光相加,然后和纹理相乘,最后计算镜面光并且相加。


#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 <math.h>#include <GL/glut.h>GLFrame             viewFrame;
GLFrustum           viewFrustum;
GLTriangleBatch     sphereBatch;
GLMatrixStack       modelViewMatrix;
GLMatrixStack       projectionMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager     shaderManager;GLuint  ADSTextureShader;   // The textured diffuse light shader
GLint   locAmbient;         // The location of the ambient color
GLint   locDiffuse;         // The location of the diffuse color
GLint   locSpecular;        // The location of the specular color
GLint   locLight;           // The location of the Light in eye coordinates
GLint   locMVP;             // The location of the ModelViewProjection matrix uniform
GLint   locMV;              // The location of the ModelView matrix uniform
GLint   locNM;              // The location of the Normal matrix uniform
GLint   locTexture;
GLuint  texture;// 加载纹理函数
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{GLbyte *pBits;int nWidth, nHeight, nComponents;GLenum eFormat;// Read the texture bitspBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);if (pBits == NULL)return false;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);glPixelStorei(GL_UNPACK_ALIGNMENT, 1);glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,eFormat, GL_UNSIGNED_BYTE, pBits);free(pBits);if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||minFilter == GL_LINEAR_MIPMAP_NEAREST ||minFilter == GL_NEAREST_MIPMAP_LINEAR ||minFilter == GL_NEAREST_MIPMAP_NEAREST)glGenerateMipmap(GL_TEXTURE_2D);return true;
}// 初始化渲染环境
void SetupRC(void)
{// 1.渲染颜色glClearColor(0.0f, 0.0f, 0.0f, 1.0f);//2.开启渲染模式:深度检测,遮挡剔除glEnable(GL_DEPTH_TEST);glEnable(GL_CULL_FACE);//3.初始化渲染器shaderManager.InitializeStockShaders();//4.设置好摄像机的位置viewFrame.MoveForward(4.0f);// 5.创建对象gltMakeSphere(sphereBatch, 1.0f, 26, 13);//6.加载渲染器程序代码ADSTextureShader = gltLoadShaderPairWithAttributes("ADSTexture.vp", "ADSTexture.fp", 3, GLT_ATTRIBUTE_VERTEX, "vVertex",GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexture0");//7.得到对应统一值的位置并且做进一步修改locAmbient = glGetUniformLocation(ADSTextureShader, "ambientColor");locDiffuse = glGetUniformLocation(ADSTextureShader, "diffuseColor");locSpecular = glGetUniformLocation(ADSTextureShader, "specularColor");locLight = glGetUniformLocation(ADSTextureShader, "vLightPosition");locMVP = glGetUniformLocation(ADSTextureShader, "mvpMatrix");locMV = glGetUniformLocation(ADSTextureShader, "mvMatrix");locNM = glGetUniformLocation(ADSTextureShader, "normalMatrix");locTexture = glGetUniformLocation(ADSTextureShader, "colorMap");//8.生成纹理,并且绑定在一个宏上,并且从文件中加载glGenTextures(1, &texture);glBindTexture(GL_TEXTURE_2D, texture);LoadTGATexture("CoolTexture.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
}// 清除
void ShutdownRC(void)
{//相当于析构函数glDeleteTextures(1, &texture);
}// 真正的渲染场景程序
void RenderScene(void)
{//1.设置计时器static CStopWatch rotTimer;// 2.清除颜色缓冲区,深度缓冲区glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//3.对物体进行集合变换modelViewMatrix.PushMatrix(viewFrame);modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f, 1.0f, 0.0f);//4.硬编码对应的属性GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f };GLfloat vAmbientColor[] = { 0.2f, 0.2f, 0.2f, 1.0f };GLfloat vDiffuseColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };GLfloat vSpecularColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };//绑定纹理glBindTexture(GL_TEXTURE_2D, texture);//激活渲染程序glUseProgram(ADSTextureShader);//对统一值进行赋值glUniform4fv(locAmbient, 1, vAmbientColor);glUniform4fv(locDiffuse, 1, vDiffuseColor);glUniform4fv(locSpecular, 1, vSpecularColor);glUniform3fv(locLight, 1, vEyeLight);//设置模型投影矩阵,在顶点渲染器设置gl_position用到glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());//模型矩阵,在顶点渲染器当中,计算视觉坐标系下的顶点坐标glUniformMatrix4fv(locMV, 1, GL_FALSE, transformPipeline.GetModelViewMatrix());//法线矩阵,在顶点着色器当中,计算视觉坐标系下的法线glUniformMatrix3fv(locNM, 1, GL_FALSE, transformPipeline.GetNormalMatrix());//设置纹理采样单元glUniform1i(locTexture, 0);sphereBatch.Draw();modelViewMatrix.PopMatrix();glutSwapBuffers();glutPostRedisplay();
}void ChangeSize(int w, int h)
{// Prevent a divide by zeroif (h == 0)h = 1;// Set Viewport to window dimensionsglViewport(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("Lit Texture");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;
}

这个主程序涉及了很多我们之前所提到的知识,我在每个语句上都加了注释。
重要的额SetUpRC以及RenderScene这两个函数,所执行的步骤,是我们目前为止所学的必要步骤。基本套路就是这样,可以模仿这样的步骤进行创造。

(3)丢弃片段

片段着色器设有取消处理过程而不写入任何片段颜色值(或者是深度,模板)的选项。声明discard只会使得片段程序停止运行,这个声明的一个常规用途就是执行alpha测试。普通的混合操作需要从颜色缓冲区进行一次读取,两次乘法,对颜色进行一次求和。然后将会得到的值写回颜色缓冲区。如果alpha值为0,或者非常接近0,那么片段实际上是不可见的。
绘制不可见的片段是对性能的严重侮辱,这样会在深度缓冲区创建一个不可见模式。从而导致深度测试异常。alpha测试只是检查一些阈值,并且在alpha值低于这个值的时候,完全丢弃这个片段。

if(vColorValue.a<0.1f)
{
discard;
}

使用这种特性可以创建出非常棒的侵蚀着色器(erosion shader)。侵蚀着色器可以使几何图形看起来经过了岁月的侵蚀。使用discard声明,我们可以逐个像素的控制哪个片段会进行绘制,哪个片段不会。
在客户端代码中,设置了一个基于时间的Uniform值,取值范围为1-0,覆盖10s的范围。最终结果是在10s内消散。
我们通过对云纹理进行采样,并且将一个颜色分量和倒计时变量进行比较,当颜色值大于阈值的时候,则完全丢弃片段。

// ADS Point lighting Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130// 输入每个点,法向量,纹理坐标
in vec4 vVertex;
in vec3 vNormal;
in vec2 vTexCoords0;uniform mat4   mvpMatrix;
uniform mat4   mvMatrix;
uniform mat3   normalMatrix;
uniform vec3   vLightPosition;// 需要输出到片段着色器当中做进一步计算。
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
smooth out vec2 vVaryingTexCoord;void main(void) {// 传递纹理坐标vVaryingTexCoord = vTexCoords0;// 计算视觉坐标系当中的表面法向量vVaryingNormal = normalMatrix * vNormal;// 视觉坐标系的顶点位置vec4 vPosition4 = mvMatrix * vVertex;vec3 vPosition3 = vPosition4.xyz / vPosition4.w;// 光照方向vVaryingLightDir = normalize(vLightPosition - vPosition3);// 几何变换gl_Position = mvpMatrix * vVertex;}

点渲染程序,和之前的程序并没有差别。

// ADS Point lighting Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130out vec4 vFragColor;uniform vec4       ambientColor;
uniform vec4       diffuseColor;
uniform vec4       specularColor;
uniform sampler2D  cloudTexture;
uniform float      dissolveFactor;smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
smooth in vec2 vVaryingTexCoord;void main(void){ //注意,这是灰度图,那么贴图颜色和光照颜色乘积就毫无意义。所以这里并没有乘vec4 vCloudSample = texture(cloudTexture, vVaryingTexCoord);//这种消散效果仅仅是对纹理取样进行阈值的验证,如果符合那么就丢弃if(vCloudSample.r < dissolveFactor)discard;float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));vFragColor = diff * diffuseColor;vFragColor += ambientColor;vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));if(diff != 0) {float fSpec = pow(spec, 128.0);vFragColor.rgb += vec3(fSpec, fSpec, fSpec);}}

片段渲染器,仅仅多了一条阈值验证。

    float fFactor = fmod(rotTimer.GetElapsedSeconds(), 10.0f);fFactor /= 10.0f;glUniform1f(locDissolveFactor, fFactor);torusBatch.Draw();

在主程序的RenderScene函数中,通过设置阈值的不断变化,然后传入着色器程序中。通过阈值的不断变化,来产生侵蚀的效果,耍了个小花招。

(4)卡通着色器:将纹理单元作为光源
所谓卡通着色,无非是一维贴图纹理。通常应用在计算机游戏中对一个几何图形进行渲染。使其看起来像是动画片。
卡通着色,(Toon shader, cell shading)将一个一维纹理贴图作为一个查询表,使用纹理贴图中的纯色(GL_NEAREST)填充几何图形。
基本思路是:使用漫反射光照强度(视觉空间表面法线和光线方向的点乘积)作为纹理坐标添加到一个包含逐渐变亮颜色表的一维纹理中。

#version 130// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;smooth out float textureCoordinate;uniform vec3    vLightPosition;
uniform mat4    mvpMatrix;
uniform mat4    mvMatrix;
uniform mat3    normalMatrix;void main(void) { // Get surface normal in eye coordinatesvec3 vEyeNormal = normalMatrix * vNormal;// Get vertex position in eye coordinatesvec4 vPosition4 = mvMatrix * vVertex;vec3 vPosition3 = vPosition4.xyz / vPosition4.w;// Get vector to light sourcevec3 vLightDir = normalize(vLightPosition - vPosition3);// 点乘积给我们漫反射强度,并且以此作为纹理坐标textureCoordinate = max(0.0, dot(vEyeNormal, vLightDir));// Don't forget to transform the geometry!gl_Position = mvpMatrix * vVertex;}

这里的顶点渲染器,需要的东西,注意纹理坐标的生成。

#version 130uniform sampler1D colorTable;
out vec4 vFragColor;smooth in float textureCoordinate;void main(void){ //注意,得到的纹理坐标,和colorTable进行绑定vFragColor = texture(colorTable, textureCoordinate);}

最后在片段着色器当中将纹理坐标和颜色表进行绑定。

    glGenTextures(1, &texture);glBindTexture(GL_TEXTURE_1D, texture);GLubyte textureData[4][3] = { 32,  0, 0,64,  0, 0,128, 0, 0,255, 0, 0 };glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

在初始化渲染环境当中,注意初始化颜色表。
绑定这个颜色表,在之后的渲染都用这个进行渲染。

渲染世界的OPENGL12 一些有趣的纹理着色器相关推荐

  1. OpenGL学习笔记(十三):将纹理贴图应用到四边形上,对VAO/VBO/EBO/纹理/着色器的使用方式进行总结

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7919 ...

  2. 渲染世界的OPENGL15纹理进阶-点精灵

    点精灵(Point Sprite)使用点精灵我们可以通过绘制一个3D点将一个2D纹理图像显示在任意位置上. 点精灵最常见的应用就是微粒系统.我们可以用点来表示在屏幕上移动的大量微粒,来产生一些视觉效果 ...

  3. 着色器编程_unity中的基础纹理,使用Unity Shader实现基础纹理的渲染效果

    学习通过使用Unity Shader实现基础纹理的渲染效果 目录 学习通过使用Unity Shader实现基础纹理的渲染效果 问1:详细描述一下漫反射纹理.高度纹理.法线纹理.渐变纹理和遮罩纹理? 问 ...

  4. QT实现渲染到帧缓冲区,创建其纹理.

    QT实现渲染到帧缓冲区,创建其纹理 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 渲染到帧缓冲区中并将其用作纹理. 帧缓冲区示例显示了如何渲染到帧缓冲区,创建其纹理 ...

  5. Turing渲染着色器网格技术分析

    Turing渲染着色器网格技术分析 图灵体系结构通过使用 网格着色器 引入了一种新的可编程几何着色管道.新的着色器将计算编程模型引入到图形管道中,因为协同使用线程在芯片上直接生成紧凑网格( meshl ...

  6. opengl 纹理贴到对应的位置_一步步学OpenGL(27) -《公告牌技术与几何着色器》

    教程 27 公告牌技术与几何着色器 原文: http://ogldev.atspace.co.uk/www/tutorial27/tutorial27.html CSDN完整版专栏: https:// ...

  7. unity着色器和屏幕特效开发秘笈_Oculus研发分享:开发移动VR内容时应避免的PC渲染技术...

    查看引用/信息源请点击:映维网 开发移动VR内容时应避免的PC渲染技术 (映维网 2019年11月25日)有不少开发者都是以与PC相同的方式来开发Quest游戏,但这可能会导致优化性能方面出现大量困难 ...

  8. 着色器实例 代码+注释 更新中【描边、卡通渲染、法线颜色、贴图动画等等】

    描边着色器 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader " ...

  9. 关于在寒假用两周从零手写包含模拟着色器的软渲染器这件事

    当你重新踏上旅途之后,一定要记得旅途本身的意义. --巴巴托斯 轮子哥说过,编译原理,操作系统,图形学是程序员的三大浪漫,既然以后想从事游戏方面的工作,造这个轮子是不可避免的.其实早在本科的时候我就有 ...

最新文章

  1. arraylist 后往前遍历_Java集合框架之ArrayList
  2. Exchange出站队列堵塞解决思路
  3. LACP/PAGP的定义与差别—Vecloud微云
  4. Hadoop权威指南 _02大体目录
  5. 图像处理——傅里叶变换
  6. C# 6.0语法新特性体验(二)
  7. hdoj 1015 Safecracker
  8. 仅用语音,AI 就能“脑补”你的脸! | 技术头条
  9. js富文本转换html,JS解析富文本中的html实体符号
  10. WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果?
  11. 分布式光纤振动传感技术在电力电缆管道防外力破坏的应用
  12. Unity3D游戏开发之MMD For Unity插件研究
  13. uv422转换为yuv420_利用libswscale转换yuyv422到yuv422p或rgb之间的转换, 视频翻转
  14. 2021.10.9小米一面
  15. cstdio 错误解决
  16. codewars 7kyu Vowel Count
  17. golang interface与其它类型转换
  18. jenkins+sonar 实现代码检测
  19. 根据系统的业务需求,数据库设计可以设置三张表,分别为客户信息表、账号表、交易日志记录表,其表的具体设置如下:
  20. UIAutomator2.0详解(UIDevice篇----触屏操作1)

热门文章

  1. 【漫画教程】漫画人物手部画法
  2. 三菱plc开发环境以及仿真
  3. 《人月神话》译文修订明细(1)-读者可以对照修改
  4. Excel答粉丝问:批量将单元格内容转为批注
  5. 券商股票程序化交易接口在哪里
  6. 推箱子游戏 java_Java实现推箱子游戏
  7. 2022-2028全球及中国自动运输网络(ATN)系统市场研究
  8. 小米mix2安兔兔html5跑分,【小米MIX2评测】性能:为发烧而生名副其实-中关村在线...
  9. Excel常用用特殊符号输入快捷键__2020.02.29
  10. 拉卡拉支付准确捕捉风口创新核心竞争力