我已经在墙上撞了两天了。我试图提取最简单的OpenGL Core~2.0-3.2绘图序列,以便我可以构建代码并真正理解API。我遇到的问题是,这些教程似乎从来没有为他们正在使用的OpenGL版本提供有用的标签,而且纯粹是靠运气,我发生了关于如何均衡的文档从我的上下文中请求特定版本。
我确定我现在启用了3.2核心,因为即时模式绘制会导致错误(这是一件好事!我想立即离开模式!),我已经尝试过剥离任何花哨的东西,如坐标变换或三角形缠绕,可能会搞砸我的显示器。问题是,我无法在屏幕上显示任何内容。
在此程序的先前迭代中,我确实设法在屏幕上有时使用随机坐标获得白色三角形,但在我看来,顶点并未正确设置,奇怪的位组合会产生奇怪的结果。符号在三角形出现的位置无关紧要 - 因此我的理论是顶点信息没有被正确地传递到顶点着色器,或者着色器正在破坏它。问题是,我正在查看我能找到的所有结果和日志,并且着色器可以很好地编译和链接。
我将在下面提供链接和代码,但除了在屏幕上获取三角形之外我还想知道,我可以让着色器程序将文本和/或诊断值吐出到其shaderInfoLog吗?这将极大地简化调试过程。
我咨询的各种教程都是......
http://arcsynthesis.org/gltut/Basics/Tutorial%2001.html http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Introduction https://en.wikipedia.org/wiki/Vertex_Buffer_Object http://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_(C_/_SDL) http://antongerdelan.net/opengl/hellotriangle.html http://lwjgl.org/wiki/index.php?title=The_Quad_with_DrawArrays http://lwjgl.org/wiki/index.php?title=Using_Vertex_Buffer_Objects_(VBO) http://www.opengl.org/wiki/Vertex_Rendering
http://www.opengl.org/wiki/Layout_Qualifier_(GLSL)(不在 提供代码,但我尝试的是#version 420 with layout 限定符0(in_Position)和1(in_Color))
代码(LWJGL + Groovy)
package com.thoughtcomplex.gwdg.core
import org.lwjgl.input.Keyboard
import org.lwjgl.opengl.ContextAttribs
import org.lwjgl.opengl.Display
import org.lwjgl.opengl.GL11
import org.lwjgl.opengl.GL15
import org.lwjgl.opengl.GL20
import org.lwjgl.opengl.GL30
import org.lwjgl.opengl.PixelFormat
import org.lwjgl.util.glu.GLU
import java.nio.ByteBuffer
import java.nio.FloatBuffer
/**
* Created by Falkreon on 5/21/2014.
*/
class GwDG {
static final String vertexShader = """
#version 150
in vec2 in_Position;
in vec3 in_Color;
smooth out vec3 ex_Color;
void main(void) {
gl_Position = vec4(in_Position,0.0,1.0);
ex_Color = in_Color;
}
""";
static final String fragmentShader = """
#version 150
smooth in vec3 ex_Color;
out vec4 fragColor;
void main(void) {
//fragColor = vec4(ex_Color, 1.0);
fragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
""";
static int vaoHandle = -1;
static int vboHandle = -1;
protected static int colorHandle = -1;
static int vertexShaderHandle = -1;
static int fragmentShaderHandle = -1;
static int shaderProgram = -1;
protected static FloatBuffer vboBuffer = ByteBuffer.allocateDirect(6*4).asFloatBuffer();
protected static FloatBuffer colorBuffer = ByteBuffer.allocateDirect(9*4).asFloatBuffer();
public static void main(String[] args) {
//Quick and dirty hack to get something on the screen; this *works* for immediate mode drawing
System.setProperty("org.lwjgl.librarypath", "C:\\Users\\Falkreon\\IdeaProjects\\GwDG\\native\\windows");
Display.setTitle("Test");
ContextAttribs attribs = new ContextAttribs();
attribs.profileCompatibility = false;
attribs.profileCore = true;
attribs.majorVersion = 3;
attribs.minorVersion = 2;
Display.create( new PixelFormat().withDepthBits(24).withSamples(4).withSRGB(true), attribs );
//Kill any possible winding error
GL11.glDisable(GL11.GL_CULL_FACE);
vaoHandle = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoHandle);
reportErrors("VERTEX_ARRAY");
vboHandle = GL15.glGenBuffers();
colorHandle = GL15.glGenBuffers();
vertexShaderHandle = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
fragmentShaderHandle = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
reportErrors("CREATE_SHADER");
GL20.glShaderSource( vertexShaderHandle, vertexShader );
GL20.glShaderSource( fragmentShaderHandle, fragmentShader );
GL20.glCompileShader( vertexShaderHandle );
String vertexResult = GL20.glGetShaderInfoLog( vertexShaderHandle, 700 );
if (!vertexResult.isEmpty()) System.out.println("Vertex result: "+vertexResult);
GL20.glCompileShader( fragmentShaderHandle );
String fragmentResult = GL20.glGetShaderInfoLog( fragmentShaderHandle, 700 );
if (!fragmentResult.isEmpty()) System.out.println("Fragment result: "+fragmentResult);
shaderProgram = GL20.glCreateProgram();
reportErrors("CREATE_PROGRAM");
GL20.glAttachShader( shaderProgram, vertexShaderHandle );
GL20.glAttachShader( shaderProgram, fragmentShaderHandle );
GL20.glLinkProgram(shaderProgram);
int result = GL20.glGetProgrami( shaderProgram, GL20.GL_LINK_STATUS );
if (result!=1) System.out.println("LINK STATUS: "+result);
reportErrors("SHADER_LINK");
//Attribs
int vertexParamID = GL20.glGetAttribLocation(shaderProgram, "in_Position");
int colorParamID = GL20.glGetAttribLocation(shaderProgram, "in_Color");
while (!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
//Intentional flicker so I can see if something I did freezes or lags the program
GL11.glClearColor(Math.random()/6 as Float, Math.random()/8 as Float, (Math.random()/8)+0.4 as Float, 1.0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT );
float[] coords = [
0.0f, 0.8f,
-0.8f, -0.8f,
0.8f, -0.8f
];
vboBuffer.clear();
coords.each {
vboBuffer.put it;
}
vboBuffer.flip();
float[] colors = [
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
];
colorBuffer.clear();
colors.each {
colorBuffer.put it;
}
colorBuffer.flip();
//System.out.println(dump(vboBuffer));
reportErrors("SETUP_TRIANGLE_DATA");
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vboBuffer, GL15.GL_STATIC_DRAW);
reportErrors("BIND_VBO_AND_FILL_DATA");
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorBuffer, GL15.GL_STATIC_DRAW);
reportErrors("BIND_COLOR_BUFFER_AND_FILL_DATA");
GL20.glEnableVertexAttribArray( vertexParamID );
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandle);
GL20.glVertexAttribPointer(
vertexParamID, 2, GL11.GL_FLOAT, false, 0, 0
);
GL20.glEnableVertexAttribArray( colorParamID );
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorHandle);
GL20.glVertexAttribPointer(
colorParamID, 3, GL11.GL_FLOAT, false, 0, 0
);
reportErrors("VERTEX_ATTRIB_POINTERS");
GL20.glUseProgram( shaderProgram );
GL11.glDrawArrays( GL11.GL_TRIANGLES, 0, 3 );
reportErrors("POST_RENDER");
Display.update(true);
Thread.sleep(12);
Keyboard.poll();
}
Display.destroy();
}
private static String dump(FloatBuffer f) {
String result = "[ ";
f.position(0);
//f.rewind();
for(it in 0..<f.limit()) {
result+= f.get(it);
if (it!=f.limit()-1) result+=", ";
}
result +=" ]";
f.position(0);
result;
}
private static void reportErrors(String prefix) {
int err = GL11.glGetError();
if (err!=0) System.out.println("["+prefix + "]: "+GLU.gluErrorString(err)+" ("+err+")");
}
}
不重要,但该卡是ATI Radeon HD 8550G(A8 APU的一部分),支持GL4。
我会根据要求更新更多信息,我只是不知道还有什么可能有助于诊断。
修改:我已更新上述代码,以反映Reto Koradi建议的更改。我还得到了一个使用备用顶点声明运行的代码变体:
float[] coords = [
0.0f, 0.8f,
-0.8f, -0.8f,
Math.random(), Math.random(),
//0.8f, -0.8f,
];
这实际上会在屏幕上产生某些光栅化的东西,但它完全不是我所期望的。它不是简单地重新定位右下角(右上角),而是在任何东西之间翻转,完全是白色,以及以下两种形状:
如果我替换第二个或第三个顶点,则会发生这种情况。如果我替换第一个顶点,屏幕上不会显示任何内容。因此,为了检查我关于哪个顶点实际出现在窗口中心的假设,我尝试了以下内容:
static final String vertexShader = """
#version 150
in vec2 in_Position;
in vec3 in_Color;
smooth out vec3 ex_Color;
void main(void) {
gl_Position = vec4(in_Position,0.0,1.0);
ex_Color = vec3(1.0, 1.0, 1.0);
if (gl_VertexID==0) ex_Color = vec3(1.0, 0.0, 0.0);
if (gl_VertexID==1) ex_Color = vec3(0.0, 1.0, 0.0);
if (gl_VertexID==2) ex_Color = vec3(0.0, 0.0, 1.0);
//ex_Color = in_Color;
}
""";
static final String fragmentShader = """
#version 150
smooth in vec3 ex_Color;
out vec4 fragColor;
void main(void) {
fragColor = vec4(ex_Color, 1.0);
//fragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
""";
简单,对吧?中间的顶点应该是第一个,#34;红色&#34;顶点,因为它是非可选的顶点,没有它我似乎无法在屏幕上绘制任何东西。事实并非如此。半屏块总是按预期变红,但是面向左的三角形总是我替换的任何顶点的颜色 - 替换第二个顶点使其变为绿色,替换第三个顶点使其变为蓝色。它看起来似乎都是&#34; -0.8,-0.8&#34;和&#34; 0.8,-0.8&#34;离屏幕太远以至于可见的三角形部分实际上是无限细线。但我不认为这是由于变换造成的 - 这更像是对齐问题,其任意阈值约为0.9,会将坐标射入远地。也许顶点缓冲区中的值的有效位数可能是in_Position值的指数。
为了继续向下钻取,我增加了硬编码GLSL的数量以完全忽略缓冲区 -
static final String vertexShader = """
#version 150
in vec2 in_Position;
in vec3 in_Color;
smooth out vec3 ex_Color;
void main(void) {
gl_Position = vec4(in_Position,0.0,1.0);
ex_Color = vec3(1.0, 1.0, 1.0);
if (gl_VertexID==0) {
ex_Color = vec3(1.0, 0.0, 0.0);
gl_Position = vec4(0.0, 0.8, 0.0, 1.0);
}
if (gl_VertexID==1) {
ex_Color = vec3(0.0, 1.0, 0.0);
gl_Position = vec4(-0.8, -0.8, 0.0, 1.0);
}
if (gl_VertexID==2) {
ex_Color = vec3(0.0, 0.0, 1.0);
gl_Position = vec4(0.8, -0.8, 0.0, 1.0);
}
//ex_Color = in_Color;
}
""";
这会产生所需的结果,一个漂亮的大三角形,每个顶点都有不同的颜色。显然我想从顶点缓冲区中获取相同的三角形,但它是一个非常好的开始 - 有两个顶点我至少可以告诉最终顶点射出的方向。在第一个顶点的情况下,它&& #39;肯定是 down 。
我还想出了如何在配置文件中启用调试模式,以及它在我身上随地吐出颜色缓冲区错误。好!这是一个开始。现在为什么它不会抛出大量的VBO错误?
答案 0 :(得分:1)
您的代码与核心配置文件不兼容。你的reportErrors()
实际应该开火。在核心配置文件中,您必须使用顶点数组对象(VAO)进行顶点设置。在设置顶点状态之前,您必须使用glGenVertexArrays()
生成VAO,并将其与`glBindVertexArray()绑定。
也不推荐在片段着色器中使用gl_FragColor
。您需要在核心配置文件中声明自己的out
变量,例如:
out vec4 FragColor;
...
FragColor = ...
答案 1 :(得分:0)
答案终于来自灵感 http://lwjgl.org/forum/index.php?topic=5171.0
这是相当错误的,所以让我解释一下最终是对的。我的开发环境是英特尔芯片上的java。所有java都以big-endian运行。我感到很困惑的是,我的花车的指数似乎在意义上消失了,但是看到这篇文章它最终让我感到震惊 - 如果翻转字符串就会发生最简单的方式! FloatBuffers仍然是大端的。除了本机字节顺序之外,OpenGL运行的可能性几乎为零。我咨询的lwjgl资源都没有提到这个怪癖,或者我错过了它们。
此程序中ByteBuffers的正确初始化程序为:
protected static FloatBuffer vboBuffer = ByteBuffer.allocateDirect(6*4).order( ByteOrder.nativeOrder( ) ).asFloatBuffer();
protected static FloatBuffer colorBuffer = ByteBuffer.allocateDirect(9*4).order( ByteOrder.nativeOrder( ) ).asFloatBuffer();
重要的部分是ByteOrder.nativeOrder()