2015-01-07 7 views
1

Недавно я начал изучать OpenGL, и я пытался написать программу, которая отображает бриллиант на экране с использованием VAO и VBOs с шейдерами. Мой код в основном основан на этом учебнике: https://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_%28C_/_SDL%29 и я также использовал шейдеры из учебника. Предполагается, что алмаз должен быть нарисован с использованием информации о цвете из объекта массива вершин, но вместо этого он просто нарисован в белом цвете. Похоже, что шейдеры загружаются, поэтому я думаю, что это проблема с моими объектами вершинного и буферного массивов. Может кто-то объяснить, почему мой код не работает, как я ожидал, или показать ясный пример того, как визуализировать VAO, используя цвета из массива атрибутов цвета.VAO не отображает цвет с шейдерами

package windows; 

import java.awt.Frame; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.nio.FloatBuffer; 
import java.nio.IntBuffer; 

import javax.media.opengl.GL2; 
import javax.media.opengl.GLAutoDrawable; 
import javax.media.opengl.GLCapabilities; 
import javax.media.opengl.GLEventListener; 
import javax.media.opengl.GLProfile; 
import javax.media.opengl.awt.GLCanvas; 
import javax.media.opengl.glu.GLU; 

import shaders.ShaderControl2; 

import com.jogamp.common.nio.Buffers; 

public class Test4 implements GLEventListener{ 

ShaderControl2 sc; 
FloatBuffer vertexPos, vertexCol; 
IntBuffer vao, vbo; 
GLU glu = new GLU(); 

public static void main(String[] args){ 
    GLProfile glp = GLProfile.getDefault(); 
    GLCapabilities caps = new GLCapabilities(glp); 
    GLCanvas canvas = new GLCanvas(caps); 

    Test4 t = new Test4(); 

    canvas.addGLEventListener(t); 

    Frame f = new Frame("TEST #4"); 
    f.setSize(400,400); 
    f.add(canvas); 
    f.setVisible(true); 
    f.addWindowListener(new WindowAdapter(){ 
     public void windowClosing(WindowEvent e){ 
      System.exit(0); 
     } 
    }); 
} 


@Override 
public void display(GLAutoDrawable drawable) { 
    GL2 gl = drawable.getGL().getGL2(); 
    gl.glClearColor(0, 0, 0, 1f); 
    gl.glClear(GL2.GL_COLOR_BUFFER_BIT); 

    sc.useShader(gl); 

    gl.glBindVertexArray(vao.get(0)); 
    gl.glEnableVertexAttribArray(0); 
    gl.glEnableVertexAttribArray(1); 
    gl.glDrawArrays(GL2.GL_LINE_LOOP, 0 , 4); 

    sc.dontUseShader(gl); 

} 

@Override 
public void dispose(GLAutoDrawable drawable) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void init(GLAutoDrawable drawable) { 
    GL2 gl = drawable.getGL().getGL2(); 
    System.out.println(gl.glGetString(GL2.GL_VERSION)); 

    vertexPos = Buffers.newDirectFloatBuffer(8); 
    vertexPos.put(new float[]{0f, 1f}); 
    vertexPos.put(new float[]{1f, 0f}); 
    vertexPos.put(new float[]{0f, -1f}); 
    vertexPos.put(new float[]{-1f, 0}); 
    vertexPos.flip(); 

    vertexCol = Buffers.newDirectFloatBuffer(12); 
    vertexCol.put(new float[]{1f, 0f, 0f}); 
    vertexCol.put(new float[]{0f, 1f, 0f}); 
    vertexCol.put(new float[]{0f, 0f, 1f}); 
    vertexCol.put(new float[]{1f, 1f, 1f}); 
    vertexCol.flip(); 

    vao = IntBuffer.allocate(1); 
    vbo = IntBuffer.allocate(2); 

    gl.glGenVertexArrays(1, vao); 
    gl.glGenBuffers(2, vbo); 

    int bytesPerFloat = Float.SIZE/Byte.SIZE; 

    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(0)); 
    gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertexPos.capacity() * bytesPerFloat, vertexPos, GL2.GL_STATIC_DRAW); 

    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(1)); 
    gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertexCol.capacity() * bytesPerFloat, vertexCol, GL2.GL_STATIC_DRAW); 

    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); 

    gl.glBindVertexArray(vao.get()); 
    gl.glEnableVertexAttribArray(0); 
    gl.glEnableVertexAttribArray(1); 

    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(0)); 
    gl.glVertexAttribPointer(0, 2, GL2.GL_FLOAT, false, 0, 0); 

    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(1)); 
    gl.glVertexAttribPointer(1, 3, GL2.GL_FLOAT, false, 0, 0); 

    gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); 


    sc = new ShaderControl2(); 
    sc.vSrc = sc.loadShader("v.txt"); 
    sc.fSrc = sc.loadShader("f.txt"); 

} 

@Override 
public void reshape(GLAutoDrawable drawable, int x, int y, int width, 
     int height) { 

} 

}

ShaderControl2 код:

package shaders; 

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.nio.ByteBuffer; 
import java.nio.IntBuffer; 

import javax.media.opengl.*; 

public class ShaderControl2 { 

private int vertexShaderProg, fragmentShaderProg, shaderProg; 
public String[] vSrc, fSrc; 

public String[] loadShader(String sFile){ 
    String line = new String(); 
    StringBuilder fileContent = new StringBuilder(); 

    try{ 
     InputStream is = getClass().getResourceAsStream(sFile); 
     BufferedReader br = new BufferedReader(new InputStreamReader(is)); 
     while((line = br.readLine()) != null){ 
      fileContent.append(line + "\n"); 
     } 
     is.close(); 
    } catch(Exception e){ 
     e.printStackTrace(); 
    } 
    System.out.println("Shader file content:\n" + fileContent); 
    return new String[]{fileContent.toString()}; 
} 

public void attachShader(GL2 gl){ 
    IntBuffer isCompiledVS = IntBuffer.allocate(1), isCompiledFS = IntBuffer.allocate(1), isLinked = IntBuffer.allocate(1); 
    IntBuffer vLogLength = IntBuffer.allocate(1), fLogLength = IntBuffer.allocate(1), linkLogLength = IntBuffer.allocate(1); 
    ByteBuffer vertexInfoLog, fragmentInfoLog, linkInfoLog; 
    int size; 

    vertexShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); 

    gl.glShaderSource(vertexShaderProg, 1, vSrc, null); 
    gl.glCompileShader(vertexShaderProg); 

    gl.glGetShaderiv(vertexShaderProg, GL2.GL_COMPILE_STATUS, isCompiledVS); 
    if(isCompiledVS.get(0) == 0){ 
     System.out.println("Failed to compile vertexShaderProg"); 

     gl.glGetShaderiv(vertexShaderProg, GL2.GL_INFO_LOG_LENGTH, vLogLength); 
     size = vLogLength.get(0); 
     vertexInfoLog = ByteBuffer.allocate(size); 
     gl.glGetShaderInfoLog(vertexShaderProg, size, vLogLength, vertexInfoLog); 

     for(byte b : vertexInfoLog.array()){ 
      System.err.print((char)b); 
     } 
    } 

    fragmentShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); 

    gl.glShaderSource(fragmentShaderProg, 1, vSrc, null); 
    gl.glCompileShader(fragmentShaderProg); 

    gl.glGetShaderiv(fragmentShaderProg, GL2.GL_COMPILE_STATUS, isCompiledFS); 
    if(isCompiledFS.get(0) == 0){ 
     System.out.println("Failed to compile fragmentShaderProg"); 

     gl.glGetShaderiv(fragmentShaderProg, GL2.GL_INFO_LOG_LENGTH, fLogLength); 
     size = fLogLength.get(0); 
     fragmentInfoLog = ByteBuffer.allocate(size); 
     gl.glGetShaderInfoLog(fragmentShaderProg, size, fLogLength, fragmentInfoLog); 

     for(byte b : fragmentInfoLog.array()){ 
      System.err.print((char)b); 
     } 

    } 

    shaderProg = gl.glCreateProgram(); 
    gl.glAttachShader(shaderProg, vertexShaderProg); 
    gl.glAttachShader(shaderProg, fragmentShaderProg); 

    gl.glBindAttribLocation(shaderProg, 0, "in_Position"); 
    gl.glBindAttribLocation(shaderProg, 1, "in_Color"); 

    gl.glLinkProgram(shaderProg); 

    gl.glGetProgramiv(shaderProg, GL2.GL_LINK_STATUS, isLinked); 
    if(isLinked.get(0) == 0){ 
     System.out.println("Failed to link shaderProg"); 

     gl.glGetShaderiv(shaderProg, GL2.GL_INFO_LOG_LENGTH, linkLogLength); 
     size = linkLogLength.get(0); 
     linkInfoLog = ByteBuffer.allocate(size); 
     gl.glGetProgramInfoLog(shaderProg, size, linkLogLength, linkInfoLog); 

     for(byte b : linkInfoLog.array()){ 
      System.err.print((char)b); 
     } 
    }  
} 

public int useShader(GL2 gl){ 
    gl.glUseProgram(shaderProg); 
    return shaderProg; 
} 

public void dontUseShader(GL2 gl){ 
    gl.glUseProgram(0); 
} 
} 

Shader Код

f.txt:

#version 210 
// It was expressed that some drivers required this next line to function properly 
precision highp float; 

in vec3 ex_Color; 
out vec4 gl_FragColor; 

void main(void) { 
    // Pass through our original color with full opacity. 
    gl_FragColor = vec4(ex_Color,1.0); 
} 

v.txt:

#version 210 
// in_Position was bound to attribute index 0 and in_Color was bound to attribute index 1 
in vec2 in_Position; 
in vec3 in_Color; 

// We output the ex_Color variable to the next shader in the chain 
out vec3 ex_Color; 
void main(void) { 
// Since we are using flat lines, our input only had two points: x and y. 
// Set the Z coordinate to 0 and W coordinate to 1 

gl_Position = vec4(in_Position.x, in_Position.y, 0.0, 1.0); 

// GLSL allows shorthand use of vectors too, the following is also valid: 
// gl_Position = vec4(in_Position, 0.0, 1.0); 
// We're simply passing the color through unmodified 

ex_Color = in_Color; 
} 
+0

Вы уверены, что атрибут цвета находится в местоположении 1? Вы должны установить это либо с квалификатором макета местоположения в вершинном шейдерном коде, либо с вызовом 'glBindAttribLocation() перед связыванием шейдерной программы. –

+0

Да, сразу после того, как я прикрепил два шейдера и прямо перед тем, как связать программу, я установил местоположение с помощью glBindAttribLocation (shaderProg, 0, "in_Position") и gl.glBindAttribLocation (shaderProg, 1, "in_Color") в методе attachShaders ShaderControl2 – Frosty

+0

Для меня этот код выглядит отлично. Можете ли вы добавить шейдеры?Два дополнительных совета: во-первых: повторное использование атрибутов вершин на дисплее не требуется, поскольку оно уже хранится в vao. Во-вторых: я бы отвязал vao после инициализации, чтобы последующие вызовы повлияли на его состояние. – BDL

ответ

0

Причина, по которой вы видите только белые линии, заключается в том, что программа шейдера вообще не используется.

Я не могу видеть, куда вы звоните присоединять шейдеры (вы никогда не называйте sc.attachShader (ГЛ), я добавил sc.attachShader (ГЛ) в конце метода инициализации.

Сейчас много ошибок появится.

в attachshader, когда вы создаете fragmentShaderProg вы создаете его как GL_VERTEX_SHADER, она должна быть GL_FRAGMENT_SHADER, и чуть ниже, что вы отправляете источник вершинного шейдера вместо фрагмента шейдер.

версия 210 языка GLSL не существует, измените ее на версию 130. Вещь с версией GLSL заключается в том, что она i S не зависит от версии OpenGL, https://github.com/mattdesl/lwjgl-basics/wiki/GLSL-Versions

#version 130 

Теперь добавьте в конец метода инициализации

sc.attachShader(gl) 

и изменить

fragmentShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); 
gl.glShaderSource(fragmentShaderProg, 1, vSrc, null); 

для

fragmentShaderProg = gl.glCreateShader(GL2.GL_FRAGMENT_SHADER); 
gl.glShaderSource(fragmentShaderProg, 1, fSrc, null); 

Теперь это работает.

working result

+0

Большое вам спасибо! Я знаю, что они, вероятно, кажутся глупыми ошибками, но у меня так много проблем, когда я выяснил это самостоятельно, потому что я даже не знал, действительно ли правильный код был правильным. – Frosty

+0

Добро пожаловать, я некоторое время изучаю opengl, поверьте, я не новичок в этих ошибках –

 Смежные вопросы

  • Нет связанных вопросов^_^