JOGL 没有渲染任何东西
Posted
技术标签:
【中文标题】JOGL 没有渲染任何东西【英文标题】:JOGL is not rendering anything 【发布时间】:2014-01-05 23:21:13 【问题描述】:我正在尝试使用数组缓冲区渲染三个点,但我无法渲染任何内容。 这是我的代码:
import java.nio.*;
import javax.media.opengl.*;
public class SimpleScene implements GLEventListener
private GL3 gl;
int myIdentityShader;
@Override
public void display(GLAutoDrawable drawable)
gl.glClear(GL3.GL_COLOR_BUFFER_BIT);
gl.glUseProgram(myIdentityShader);
gl.glDrawArrays(GL3.GL_POINTS, 0, 3);
@Override
public void dispose(GLAutoDrawable drawable)
gl.glDeleteProgram(myIdentityShader);
gl.glDeleteVertexArrays(1, vertexArrayObject, 0);
@Override
public void init(GLAutoDrawable drawable)
gl = drawable.getGL().getGL3();
try
myIdentityShader = createShaderProgram();
catch (Exception e)
e.printStackTrace();
return;
gl.glPointSize(30);
gl.glClearColor(0.7f, 0, 0, 1);
float[] floatData =
0.25f, -0.25f, 0.5f, 1.0f,
-0.25f, -0.25f, 0.5f, 1.0f,
0.25f, 0.25f, 0.5f, 1.0f
;
FloatBuffer data = FloatBuffer.allocate(3 * 4);
for (int i=0;i<12;i++)
data.put(floatData[i]);
gl.glGenVertexArrays(1, vertexArrayObject, 0);
gl.glBindVertexArray(vertexArrayObject[0]);
int[] buffers = new int[1];
gl.glGenBuffers(1, buffers, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, buffers[0]);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, data.capacity(), data, GL3.GL_STATIC_DRAW);
gl.glVertexAttribPointer(2, 4, GL3.GL_FLOAT, false, 0, 0);
gl.glEnableVertexAttribArray(2);
@Override
public void reshape(GLAutoDrawable drawable, int arg1, int arg2, int arg3,
int arg4)
// TODO Add reshape code
private String vertexShader = "#version 130 \n" +
"in vec4 position; \n" +
"void main(void) \n" +
" \n" +
" gl_Position = position; \n" +
" \n";
private String fragmentShader = "#version 130 \n" +
"out vec4 vFragColor; \n" +
"void main(void) \n" +
" \n" +
" vFragColor = vec4(0.0, 0.8, 1.0, 1.0); \n" +
" \n";
private int[] vertexArrayObject = new int[1];
private int createShaderProgram() throws Exception
int hVertexShader, hFragmentShader, hShaderProgram;
int[] successTest = new int[] 1;
hVertexShader = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
hFragmentShader = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);
gl.glShaderSource(hVertexShader, 1, new String[] vertexShader, null);
gl.glShaderSource(hFragmentShader, 1, new String[] fragmentShader, null);
gl.glCompileShader(hVertexShader);
gl.glCompileShader(hFragmentShader);
gl.glGetShaderiv(hVertexShader, GL3.GL_COMPILE_STATUS, successTest, 0);
if (successTest[0] == 0)
byte[] infoLog = new byte[1024];
gl.glGetShaderInfoLog(hVertexShader, 1024, null, 0, infoLog, 0);
gl.glDeleteShader(hVertexShader);
gl.glDeleteShader(hFragmentShader);
throw new Exception("Vertex shader compilation failed with: " + new String(infoLog));
gl.glGetShaderiv(hFragmentShader, GL3.GL_COMPILE_STATUS, successTest, 0);
if (successTest[0] == 0)
byte[] infoLog = new byte[1024];
gl.glGetShaderInfoLog(hFragmentShader, 1024, null, 0, infoLog, 0);
gl.glDeleteShader(hVertexShader);
gl.glDeleteShader(hFragmentShader);
throw new Exception("Fragment shader compilation failed with: " + new String(infoLog));
hShaderProgram = gl.glCreateProgram();
gl.glAttachShader(hShaderProgram, hVertexShader);
gl.glAttachShader(hShaderProgram, hFragmentShader);
gl.glBindAttribLocation(hShaderProgram, 2, "position");
gl.glLinkProgram(hShaderProgram);
gl.glGetProgramiv(hShaderProgram, GL3.GL_LINK_STATUS, successTest, 0);
if (successTest[0] == 0)
byte[] infoLog = new byte[1024];
gl.glGetProgramInfoLog(hShaderProgram, 1024, null, 0, infoLog, 0);
gl.glDeleteProgram(hShaderProgram);
throw new Exception("Shader linking failed with: " + new String(infoLog);
gl.glDeleteShader(hVertexShader);
gl.glDeleteShader(hFragmentShader);
return hShaderProgram;
我绝对确定着色器和 createShaderProgram 方法是正确的。当我使用 glVertexAttrib4fv 时,所有三个点都被渲染在同一个位置(如预期的那样),但是当我使用 glVertexAttribPointer 时,什么都没有被渲染并且没有错误(glGetError 返回 0)。 我发现如果属性索引为 0,glVertexAttrib4fv 不会发送坐标,从而导致所有点都呈现在屏幕的中心。 glVertexAttribPointer 不会发生这种情况,因此会发送坐标。
【问题讨论】:
为什么要启用顶点属性数组#2?不应该查询顶点属性数组匹配位置的索引还是使用glBindAttribLocation强制定位? 我在createShaderProgram方法中使用glBindAttribLocation,我也试过glGetAttribLocation,还是不行。 好的,那么 glBufferData 中缓冲区的大小不应该以字节为单位吗?我相信 FloatBuffer.capacity() 是元素的数量。 我意识到了这一点并试图做一个更大的缓冲区,仍然没有。 在我的项目中,我必须使用三角形,但由于我没有得到任何渲染,我使用点只是为了调试目的,所以即使所有三个点重叠,我也可以看到一些东西。跨度> 【参考方案1】:您正在低效地使用顶点数组对象。使用 VAO 的全部意义在于您不必设置顶点属性。指针并在每次绘制某些东西时启用/禁用指针。在初始化 VAO 时设置指针,因为它会跟踪此状态,所以您只需在每次要绘制内容时更改绑定的 VAO。
但是,您的实际问题是您从未将顶点着色器中的顶点属性 position
绑定到通用属性位置 2。大多数 GLSL 实现将自动分配该顶点属性位置 0,尽管这不是必需的行为(因此不要依赖它)。您可以在链接程序后按名称查询该属性的位置(glGetAttribLocation
),也可以自己绑定属性位置(glBindAttribLocation
)。无论哪种情况,您都必须匹配指向着色器中属性的指针的属性位置。
当我使用 glVertexAttrib4fv 时,所有三个点都渲染在同一个位置,但是当我使用 glVertexAttribPointer 时,什么都没有渲染并且没有错误(glGetError 返回 0)。
这是意料之中的,glVertexAttrib4fv (...)
设置了一个常量值,用于从该位置提取数据的每个顶点着色器调用。虽然它确实需要一个指针(在 C 语言绑定中),但该指针只是 OpenGL 传递数组的方式。如果在调用完成后更改指向的数据的值,则不会发生任何事情。这就是为什么有不同类的函数来设置顶点数组pointers的原因。
更新:
看到您为这个问题更新的代码后,真正的问题出现了。在 Java 中,当您使用 FloatBuffer.put (...)
时,它会增加缓冲区的基地址(当您调用 glVertexAttribPointer (...)
时,JOGL 使用该基地址)。您需要通过调用FloatBuffer.flip (...)
来翻转缓冲区,这将有效地倒回缓冲区,以便 JOGL 将从缓冲区中的第一个元素开始读取。
【讨论】:
感谢您的回答。我实际上将 createShaderProgram 中的顶点属性位置绑定到 2。我也尝试使用 glGetAttribLocation,但仍然没有呈现任何内容。如果位置不匹配,则将在屏幕中心渲染点。会不会是坐标有问题? @user1973167:您能否更新您的问题以显示获取/设置属性位置的函数的实现?根据您对问题的描述,我不相信您做得正确。 @user1973167:仔细查看您的代码后,我认为问题在于您没有flipped
FloatBuffer,而是将其直接传递给 JOGL。 put
每次调用时都会增加起始地址,flip
会将其重置为缓冲区的开头。以上是关于JOGL 没有渲染任何东西的主要内容,如果未能解决你的问题,请参考以下文章