求助,关于游戏更新出现的问题glcompileshaderarb Shader Failed

拒绝访问 | www. | 百度云加速
请打开cookies.
此网站 (www.) 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(39ba0d-ua98).
重新安装浏览器,或使用别的浏览器问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
opengl初学者寻求大神帮助,在运行opengl程序时出现如下图所示的错误运行环境:win10 64位,visual studio2010 32位程序如下:
// main.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include &iostream&
#define GLEW_STATIC
#include &glew.h&
#include &glfw3.h&
//键盘回调函数
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mode);
const GLuint WIDTH = 800, HEIGHT = 600;
const GLchar *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3\n"
"void main()\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
const GLchar *fragmentShaderSource = "#version 330 core\n"
"out vec4\n"
"void main()\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
int _tmain(int argc, _TCHAR* argv[])
std::cout && "Starting GLFW context, OpenGL 3.3" && std::
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//创建一个glfw窗口对象,从而能够使用glfw的函数
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
//设置回调函数
glfwSetKeyCallback(window, key_callback);
//设置glew能够使用现代方法去检索函数指针及扩展
glewExperimental = GL_TRUE;
glewInit();
//定义视图位置
glViewport(0, 0, WIDTH, HEIGHT);
//构建和编译着色程序
//定点着色
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
//检查编译错误
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout && "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" && infoLog && std::
//分段着色器
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
if (!success)
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout && "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" && infoLog && std::
//链接着色器
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//检查连接错误
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout && "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" && infoLog && std::
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//设置顶点数据(或缓存)和顶点属性
/*GLfloat vertices[] = {
//第一个三角形
0.5f, 0.f,
0.5f, -0.5f,
-0.5f, 0.5f,
//第二个三角形
0.5f, -0.5f,
-0.5f, -0.5f,
-0.5f, 0.5f
//定义顶点数组
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
//定义索引数组
GLuint indices[] = {
//VBO顶点缓存对象,VAO顶点数组对象,EBO索引缓冲对象
//EBO是一个想顶点缓冲对象VBO一样的缓冲,它专门储存索引,
//OpenGL调用这些顶点的索引来绘制
GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);//生成VAO
glGenBuffers(1, &VBO);//创建VBO
glGenBuffers(1, &EBO);
//首先绑定顶点数组对象,然后绑定和设置顶点缓存和属性指针
glBindVertexArray(VAO);//绑定VAO
//复制顶点数组到缓冲中提供给OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//复制索引数组到缓冲中提供给OpenGL使用
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
//解绑VBO和EBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//画第一个三角形
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glfwTerminate();
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
是因为链接的库的原因,建议在使用opengl其他库时,如glfw,glew,soil等,下载这些包的源代码,然后用visual stdio构建,将其生成的.lib库复制到你opengl所需链接库的文件夹里
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
图1-1顶点着色器工作原理
? Attribute变量(属性变量)只能用于顶点着色器中,而不能在片元着色器中使用。一般用于每个顶点都各自不同的量,如顶点位置、颜色等。
Uniforms变量(一致变量)用来将数据值从应用程其序传递到顶点着色器或者片元着色器。一般用于对同一组顶点组成的单个3D物体中所有顶点都相同的量,如当前的光源位置、总变换矩阵等。
? Varying变量(易变变量)是从顶点着色器传递到片元着色器的数据变量。顶点着色器可以使用易变变量来传递需要插值的颜色、法向量、纹理坐标等任意值。例如:上面代码中应用程序中由顶点着色器传入片元着色器中的vColor变量。
? gl_Position顶点着色器从应用程序中获得原始的顶点位置数据,这些原始的顶点数据在顶点着色器中经过平移、旋转、缩放等数学变换后,生成新的顶点位置。新的顶点位置通过在顶点着色器中写入gl_Position传递到渲染管线的后继阶段继续处理。
? gl_PointSize顶点着色器中可以计算一个点的大小(单位为像素),并将其赋值给gl_PointSize(标量float类型)以传递给渲染管线。如果没有明确赋值的话,就是采用默认值1了。gl_PointSize的值一般只有在采用了点绘制方式之后才有意义。
1.2、 片元着色器
(1) 片元着色器代码
pre //设置工作精度
varying vec4 vC //接收从顶点着色器过来的顶点颜色数据
varying vec2 vTextureC //接收从顶点着色器过来的纹理坐标
uniform sampler2D sT //纹理采样器,代表一幅纹理
void main() {
gl_FragColor = texture2D(sTexture, vTextureCoord) * vC //进行纹理采样
此片元着色器的主要功能为根据接收的记录片元纹理坐标的易变变量中的纹理坐标,调用texture2D内建函数从采样器中进行纹理采样,得到此片元的颜色值。最后,将采样到的颜色值传给gl_FragColor内建变量,完成片元的着色。
(2) 片元着色器介绍
片元着色器是一个处理片元值及其相关联数据的可编程单元,片元着色器可执行纹理的访问、颜色的汇总、雾化等操作,每片元执行一次。
片元着色器替代了纹理、颜色求和、雾以及Alpha测试,这一部分是需要开发者自己开发的。
图2-1 片元着色器工作原理
? Varying指的是从顶点着色器传递到片元着色器的数据变量。
gl_FragColor(vec4类型)内置变量用来由片元着色器计算完成的片元颜色值,此颜色值将送入渲染管线的后继阶段进行处理,例如片元着色器中gl_FragColor = vColor。
2. 加载着色器脚本代码loadShader方法的介绍
*shader的类型 GLES20.GL_VERTEX_SHADER GLES20.GL_FRAGMENT_SHADER
*shader的脚本字符串
private int loadShader( int shaderType,String source ) {
//创建一个新shader
int shader = GLES20.glCreateShader(shaderType);
//若创建成功则加载shader
if (shader != 0) {
//加载shader的源代码
GLES20.glShaderSource(shader, source);
//编译shader
GLES20.glCompileShader(shader);
//存放编译成功shader数量的数组
int[] compiled = new int[1];
//获取Shader的编译情况
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
//若编译失败则显示错误日志并删除此shader
Log.e(TAG, "Could not compile shader " + shaderType + ":");
Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
该方法中主要为三个方法
GLES20.glCreateShader(shaderType);
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
3.1. GLES20.glCreateShader(shaderType);
用glCreateShader创建一个容纳shader的容器,称为shader容器。
方法参数:
GLES20.GL_VERTEX_SHADER (顶点shader)
GLES20.GL_FRAGMENT_SHADER (片元shader)
函数原型为:
int glCreateShader (int type)
如果调用成功的话,函数将返回一个整形的正整数作为shader容器的id。
3.2. GLES20.glShaderSource(shader, source);
接下来,要在创建好的shader容器中添加shader的源代码。源代码应该以字符串数组的形式表示。当然,也可以只用一个字符串来包含所有的源代码。
glShaderSource函数的原型如下:
void glShaderSource (int shader, String string)
参数含义:
shader是代表shader容器的id(由glCreateShader返回的整形数);
strings是包含源程序的字符串数组;
3.3. GLES20.glCompileShader(shader);
最后,使用glCompileShader函数来对shader容器中的源代码进行编译。
函数的原型如下:
void glCompileShader (int shader)
参数含义:
shader是代表shader容器的id
调试一个shader是非常困难的。shader的世界里没有printf,无法在控制台中打印调试信息。但是可以通过一些OpenGL提供的函数来获取编译和连接过程中的信息。
在编译阶段使用glGetShaderiv获取编译情况,在连接阶段使用glGetProgramiv获取连接情况。
当错误产生的时候,还可以从InfoLog中获得更多的信息。InfoLog中存储了关于上一个操作执行时的相关信息,比如编译阶段的警告和错误,以及连接阶段产生的问题。不幸的是对于错误信息没有统一的标准,所以不同的硬件或驱动程序将提供不同的错误信息。
编译阶段使用glGetShaderInfoLog获取编译错误,
(1) 编译阶段使用glGetShaderiv获取编译情况
void glGetShaderiv (int shader, int pname, int[] params, int offset)
参数含义:
shader是一个shader的id;
pname使用GL_COMPILE_STATUS;
params是返回值,如果一切正常返回GL_TRUE代,否则返回GL_FALSE。
(2) 编译阶段使用glGetShaderInfoLog获取编译错误
函数原型:
String glGetShaderInfoLog (int shader)
参数含义:
shader是一个顶点shader或者片元shader的id
这里值得一说的是,笔者随便打印了一个shader的编译错误,得出的string字符串却为空,不知原因?????。
(3) 在连接阶段使用glGetProgramiv获取连接情况
函数原型:
void glGetProgramiv (int program, int pname, int[] params, int offset)
参数含义:
program是一个着色器程序的id;
pname是GL_LINK_STATUS;
param是返回值,如果一切正常返回GL_TRUE代,否则返回GL_FALSE。
(4) 在连接阶段使用glGetProgramInfoLog获取连接错误
函数原型:
String glGetProgramInfoLog (int program)
参数含义:
program是一个着色器程序的id;
对于连接错误的打印,因为尚没有遇到过,所以不知道打印字符串的信息。
(5) 清理shader的glDeleteShader方法
当不再需要某个shader或某个程序的时候,需要对其进行清理,以释放资源。前面,提到过如何向一个程序中添加一个shader。这里可调用下面的函数来将一个shader从一个程序中清除掉:
函数原型:
void glDeleteShader (int shader);
参数含义:
shader是要被排除的顶点shader或者片元shader的id
如果,一个shader被删除之前没有从相应的程序中排除,那么这个shader不会被实际删除,而只是被标记为被删除;当shader被从程序中排除的时候,才会被真正地删除。
3. 生成着色器程序id的createProgram方法介绍
//创建shader程序的方法
private int createProgram(String vertexSource, String fragmentSource) {
//加载顶点着色器
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
//加载片元着色器
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0) {
//创建着色器程序
int program = GLES20.glCreateProgram();
//若程序创建成功则向程序中加入顶点着色器与片元着色器
if (program != 0) {
//向程序中加入顶点着色器
GLES20.glAttachShader(program, vertexShader);
//向程序中加入片元着色器
GLES20.glAttachShader(program, pixelShader);
//链接程序
GLES20.glLinkProgram(program);
//存放链接成功program数量的数组
int[] linkStatus = new int[1];
//获取program的链接情况
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
//若链接失败则报错并删除程序
if (linkStatus[0] != GLES20.GL_TRUE) {
Log.e(TAG, "Could not link program: ");
Log.e(TAG, GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
3.1. glCreateProgram
在连接shader之前,首先要创建一个容纳程序的容器,称为着色器程序容器。可以通过glCreateProgram函数来创建一个程序容器。
函数的原型如下:
int glCreateProgram ()
如果函数调用成功将返回一个整形正整数作为该着色器程序的id
3.2. glAttachShader
接下来,我们要将shader容器添加到程序中。这时的shader容器不一定需要被编译,他们甚至不需要包含任何的代码。我们要做的只是将shader容器添加到程序中。使用glAttachShader函数来为程序添加shader容器。
函数的原型如下:
void glAttachShader (int program, int shader)
参数含义:
program是着色器程序容器的id;
shader是要添加的顶点或者片元shader容器的id。
如果你同时拥有了,顶点shader和片元shader,需要分别将他们各自的两个shader容器添加的程序容器中。
3.3. glLinkProgram
最后,使用glLinkProgram来连接程序。
函数的原型如下:
void glLinkProgram (int program)
参数含义:
program是着色器程序容器的id
在连接操作执行以后,可以任意修改shader的源代码,对shader重新编译不会影响整个程序,除非重新连接程序。
3.4. glUseProgram
在连接了程序以后,我们可以使用glUseProgram函数来加载并使用连接好的程序。glUseProgram函数原型如下:
void glUseProgram (int program)
参数含义:
program是要使用的着色器程序的id,
如果将program设置为0,表示使用固定功能管线。如果程序已经在使用的时候,对程序进行重新编译,编译后的应用程序会自动替代以前的那个被调用,这时你不需要再次调用这个函数。
4. 获取指向顶点着色器相应数据的Index(glGetAttribLocation方法, glGetUniformLocation方法)
public int mP //自定义渲染管线程序id
public int muMVPMatrixH //总变换矩阵引用id
public int maPositionH //顶点位置属性引用id
public int maTextureH //顶点纹理坐标属性引用id
public int maColorH //顶点颜色坐标属性引用id
//基于顶点着色器与片元着色器创建着色器程序, 生成着色器程序id
mProgram = createProgram(mVertexShader, mFragmentShader);
//获取指向着色器中aPosition的index
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取指向着色器中aTextureCoord的index
maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
//获取指向着色器中aColor的index
maColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
//获取指向着色器中uMVPMatrix的index
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
glGetAttribLocation
调用 glGetAttribLocation 来获取顶点着色器中,指定attribute名的index。以后就可以通过这个index向顶点着色器中传递数据。获取失败则返回-1。
5. 向顶点着色器中传递数据
在创建了定点着色器和片源着色器后,我们在OpenGL中如何使用这两个着色器呢,我们从下面的示例代码来学习。
使用第4节获取的指向顶点着色器相应数据的各个Index,就能将我们自己定义的顶点数据、顶点颜色数据以及纹理顶点映射数据传递到顶点着色器当中了。在传递数据前先要调用GLES20.glUseProgram(mProgram);方法使用我们在第3节创建的着色器程序mProgram。
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//设置缓冲区起始位置
mRectBuffer.position(0);
//顶点位置数据传入着色器
GLES20.glVertexAttribPointer(maPositionHandle,
GLES20.GL_FLOAT,
mRectBuffer);
//顶点颜色数据传入着色器中
GLES20.glVertexAttribPointer(maColorHandle, 4, GLES20.GL_FLOAT, false, 4*4, mColorBuffer);
//顶点坐标传递到顶点着色器
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 20, mRectBuffer);
//允许使用顶点坐标数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
//允许使用顶点颜色数组
GLES20.glDisableVertexAttribArray(maColorHandle);
//允许使用定点纹理数组
GLES20.glEnableVertexAttribArray(maTextureHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
//三角形绘制方式
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
5.1. glUseProgram
在连接了程序以后,我们可以使用glUseProgram函数来加载并使用连接好的程序。glUseProgram函数原型如下:
void glUseProgram (int program)
参数含义:
program是要使用的着色器程序的id,
如果将program设置为0,表示使用固定功能管线。如果程序已经在使用的时候,对程序进行重新编译,编译后的应用程序会自动替代以前的那个被调用,这时你不需要再次调用这个函数。
5.2. glVertexAttribPointer
glVertexAttribPointer — 定义顶点属性数组
函数原型:
void glVertexAttribPointer ( int indx,
boolean normalized,
int stride,
Buffer ptr )
参数含义:
index 指定要修改的顶点着色器中顶点属性的索引值
size 指定每个顶点属性的组件数量。必须为1、2、3或者4。如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
type 指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。
normalized指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。
stride 指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。如果normalized被设置为GL_TRUE,意味着整数型的值会被映射至区间[-1,1](有符号整数),或者区间[0,1](无符号整数),反之,这些值会被直接转换为浮点值而不进行归一化处理。
Ptr顶点的缓冲数据
5.3. 启用或者禁用顶点属性数组
要启用或者禁用顶点属性数组,调用glEnableVertexAttribArray和glDisableVertexAttribArray传入参数index。如果启用,那么当glDrawArrays或者glDrawElements被调用时,顶点属性数组会被使用。
5.4. glActiveTexture
glActiveTexture — 选择活动纹理单元
函数原型:
void glActiveTexture (int texture)
参数含义:
texture指定哪一个纹理单元被置为活动状态。texture必须是GL_TEXTUREi之一,其中0 &= i & GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,初始值为GL_TEXTURE0。
glActiveTexture 确定了后续的纹理状态改变影响哪个纹理,纹理单元的数量是依据该纹理单元所被支持的具体实现。
阅读(1180)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'15、OpenGL ES 2.0 Shader相关介绍',
blogAbstract:'\r\n转载请保留出处:'
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}加载渲染器到OpenGL中
本文所属图书&>&
本书主要介绍了游戏最基本的理论内容,包括图层、矩阵、多线程以及游戏素材,在介绍理论的同时也给出了相关的代码;以及具体Android游戏的开发流程和代码分析,介绍了两款游戏的编写方法:一款是大家耳熟能详的捕...&&
int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexShaderHandle != 0)
&&& GLES20.glShaderSource(vertexShaderHandle, vertexShader);
&&& GLES20.glCompileShader(vertexShaderHandle);
&&& final int[] compileStatus = new int[1];
&&& GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
&&& if (compileStatus[0] == 0)
&&&&&&& GLES20.glDeleteShader(vertexShaderHandle);
&&&&&&& vertexShaderHandle = 0;
if (vertexShaderHandle == 0)
&&& throw new RuntimeException(&Error creating vertex shader.&);
首先,我们创建一个渲染对象。如果创建成功,将得到一个对象的引用。然后使用这个引用传入渲染源代码,然后编译它。我们可以从OpenGL中得到状态并查看编译是否成功。如果出现错误,可以使用GLES20.glGetShaderInfoLog(shader)找出原因。我们以同样的步骤加载片段渲染器。
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。
文章下载读书}

我要回帖

更多关于 gl compile 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信