簡體   English   中英

LWJGL OpenGL將頂點傳遞到着色器

[英]LWJGL OpenGL passing a vertex to a shader

如果我傳遞的浮點數組包含3個浮點,則表示不含W分量的頂點的XYZ,然后將其傳遞給VBO,然后告訴着色器中的輸入變量使用VBO的內容,但是此輸入變量是vec4類型,着色器會將w組件設置為1嗎? 另外,頂點是否將由着色器規范化?

編輯

MainDisplay類:

package com.dryadengine.gui;

import com.dryadengine.core.Model;
import com.dryadengine.framework.OBJLoader;
import com.dryadengine.framework.ShaderFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.util.vector.Matrix4f;

/**
 *
 * @author Roy
 */
public class MainDisplay {

    private Model bunny;
    private FloatBuffer vbo;
    private Matrix4f mProjection;
    private Matrix4f mView;
    private Matrix4f mModel;
    private int shaderProgramID;
    private int vboID;
    private int vPositionID;
    private int mProjectionID;
    private int mViewID;
    private int mModelID;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        MainDisplay md = new MainDisplay();
        md.create();
        md.init();
        md.run();
    }

    public MainDisplay() {

    }

    public void create() {
        try {
            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.setTitle("Dryad Engine 1.0.0");
            Display.setFullscreen(false);
            Display.setResizable(true);
            Display.create();
        } catch (LWJGLException ex) {
            Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
            System.exit(-1);
        }
    }

    public void init() {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        try {
            shaderProgramID = ShaderFactory.createShaderProgram("vertexShader", "fragmentShader");
            glUseProgram(shaderProgramID);
            bunny = OBJLoader.parseOBJ(new File("src/com/dryadengine/assets/bunny.obj"));
            vbo = BufferUtils.createFloatBuffer(bunny.getFaces().size() * 3 * 3);
            float[] vertexData = new float[bunny.getFaces().size() * 3 * 3];
//            System.out.println("PRINTING 10 first faces info : ");
//            for (int i = 0; i < 10; i++) {
//                System.out.println("FACE #" +(i+1));
//                for (int j = 0; j < 3; j++) {
//                    System.out.println("VERTEX #" +(j + 1));
//                    System.out.println(bunny.getFaces().get(i).getVertices()[j].x + ", " +bunny.getFaces().get(i).getVertices()[j].y+ ", " +bunny.getFaces().get(i).getVertices()[j].z);
//                }
//            }
            for (int i = 0; i < bunny.getFaces().size(); i++) {
                for (int j = 0; j < 3; j++) {
                    //System.out.println("placing new vertex at cell #" +((i * 3 + j) * 3));
                    vertexData[(i * 3 + j) * 3] = bunny.getFaces().get(i).getVertices()[j].x;
                    //System.out.println("placing new vertex at cell #" +((i * 3 + j) * 3 + 1));
                    vertexData[(i * 3 + j) * 3 + 1] = bunny.getFaces().get(i).getVertices()[j].y;
                    //System.out.println("placing new vertex at cell #" +((i * 3 + j) * 3 + 2));
                    vertexData[(i * 3 + j) * 3 + 2] = bunny.getFaces().get(i).getVertices()[j].z;
                }
            }
            vbo.put(vertexData);
            vbo.flip();
            vboID = glGenBuffers();
            glBindBuffer(GL_ARRAY_BUFFER, vboID);
            glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);
            vPositionID = glGetAttribLocation(shaderProgramID, "vPosition");
            glEnableVertexAttribArray(vPositionID);
            mProjection = new Matrix4f();
            float fieldOfView = 60f;
            float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
            float nearPlane = 0.1f;
            float farPlane = 100f;
            float yScale = (float)(1.0f / Math.tan((fieldOfView / 2.0f) * (float)(Math.PI / 180d)));
            float xScale = yScale / aspectRatio;
            float frustum_length = farPlane - nearPlane;
            mProjection.m00 = xScale;
            mProjection.m11 = yScale;
            mProjection.m22 = -((farPlane + nearPlane) / frustum_length);
            mProjection.m23 = -1;
            mProjection.m32 = -((2 * nearPlane * farPlane) / frustum_length);
            mProjection.m33 = 0;
            mView = new Matrix4f();
            mView.m23 = -5;
            mModel = new Matrix4f();
            mProjectionID = glGetUniformLocation(shaderProgramID, "mProjection");
            mViewID = glGetUniformLocation(shaderProgramID, "mView");
            mModelID = glGetUniformLocation(shaderProgramID, "mModel");
            glEnable(GL_CULL_FACE);
            glCullFace(GL_BACK);
            glEnable(GL_DEPTH_TEST);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void run() {
        int fps = 0;
        long lastCheck = System.nanoTime();
        while (!Display.isCloseRequested()) {
            if (Display.isVisible()) {
                render();
            }
            if (Display.wasResized()) {
                resize(Display.getWidth(), Display.getHeight());
            }
            if (System.nanoTime() - lastCheck >= 1000000000) {
                System.out.println("FPS : " +fps);
                fps = 0;
                lastCheck = System.nanoTime();
            }
            fps++;
            Display.update();
            Display.sync(60);
        }
        destroy();
    }

    public void render() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        FloatBuffer fb1 = BufferUtils.createFloatBuffer(16);
        FloatBuffer fb2 = BufferUtils.createFloatBuffer(16);
        FloatBuffer fb3 = BufferUtils.createFloatBuffer(16);
        mProjection.store(fb1);
        mView.store(fb2);
        mModel.store(fb3);
        fb1.flip();
        fb2.flip();
        fb3.flip();
        glUniformMatrix4(mProjectionID, false, fb1);
        glUniformMatrix4(mViewID, false, fb2);
        glUniformMatrix4(mModelID, false, fb3);
        glVertexAttribPointer (vPositionID, 3, GL_FLOAT, false, 0, 0);
        glDrawArrays(GL_TRIANGLES, 0, bunny.getFaces().size() * 3);
    }

    public void resize(int width, int height) {
        glViewport(0, 0, width, height);
    }

    public void dispose() {
        glDeleteProgram(shaderProgramID);
        glUseProgram(0);
        glDeleteBuffers(vboID);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    public void destroy() {
        dispose();
        Display.destroy();
    }
}

ShaderFactory類:

package com.dryadengine.framework;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;

/**
 *
 * @author Roy
 */
public class ShaderFactory {

    private static final String COMMON_SHADERS_PATH = "/com/dryadengine/shaders/";
    private static final String SHADER_EXTENSION = ".dsf";

    /**
     * 
     * @param vertexShaderName
     * @param fragmentShaderName
     * @return a shader program
     * @throws FileNotFoundException
     * @throws IOException 
     */
    public static int createShaderProgram(String vertexShaderName, String fragmentShaderName) throws FileNotFoundException, IOException {
        ArrayList<Integer> shaders = new ArrayList();
        shaders.add(ShaderFactory.compileShader(GL_VERTEX_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + vertexShaderName + SHADER_EXTENSION)));
        shaders.add(ShaderFactory.compileShader(GL_FRAGMENT_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + fragmentShaderName + SHADER_EXTENSION)));
        return ShaderFactory.linkProgram(shaders);
    }

    /**
     * 
     * @param shaderFilePath
     * @return a shader file code
     * @throws FileNotFoundException
     * @throws IOException 
     */
    private static String getShaderFileCode(String shaderFilePath) throws FileNotFoundException, IOException {
        StringBuilder shaderCode = new StringBuilder();
        String line;
        try {
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ShaderFactory.class.getResourceAsStream(shaderFilePath)))) {
                while ((line = br.readLine()) != null) {
                    shaderCode.append(line).append("\n");
                }
            }
        } catch (FileNotFoundException e) {
            throw new FileNotFoundException(e.getMessage());
        }
        return shaderCode.toString();
    }

    /**
     * 
     * @param shaderType
     * @param shaderCode
     * @return a compiled shader file id
     */
    public static int compileShader(int shaderType, String shaderCode) {
        int shaderID = glCreateShader(shaderType);
        glShaderSource(shaderID, shaderCode);
        glCompileShader(shaderID);
        int status = glGetShaderi(shaderID, GL_COMPILE_STATUS);
        if (status == GL_FALSE) {
            glDeleteShader(shaderID);
            throw new RuntimeException(glGetShaderInfoLog(shaderID, glGetShaderi(shaderID, GL_INFO_LOG_LENGTH)));
        }
        return shaderID;
    }

    /**
     * Link the vertex shader and the fragment shader to the shader program
     * @param shaders
     * @return a shader program
     */
    public static int linkProgram(ArrayList <Integer> shaders) {
        int shaderProgramID = glCreateProgram();
        for (Integer shader : shaders) {
            glAttachShader(shaderProgramID, shader);
        }
        glLinkProgram(shaderProgramID);
        int status = glGetProgrami(shaderProgramID, GL_LINK_STATUS);
        if (status == GL_FALSE) {
            glDeleteProgram(shaderProgramID);
            throw new RuntimeException(glGetShaderInfoLog(shaderProgramID, glGetProgrami(shaderProgramID, GL_INFO_LOG_LENGTH)));
        }
        for (int shader : shaders) {
            glDeleteShader(shader);
        }
        return shaderProgramID;
    }

}

OBJLoader類:

package com.dryadengine.framework;

import com.dryadengine.core.Face;
import com.dryadengine.core.Model;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.util.vector.Vector3f;

/**
 *
 * @author Roy
 */
public class OBJLoader {

    /**
     * Parse .obj file and make a model from it.
     * @param f
     * @return a model object
     * @throws FileNotFoundException
     * @throws IOException 
     */
    public static Model parseOBJ(File f) throws FileNotFoundException, IOException {
        BufferedReader br = new BufferedReader(new FileReader(f));
        String line;
        Model m;
        List<Vector3f> vertices = new ArrayList<>();
        List<Vector3f> normals = new ArrayList<>();
        List<Face> faces = new ArrayList<>();
        while ((line = br.readLine()) != null) {
            if (line.startsWith("v ")) {
                float x = Float.valueOf(line.split(" ")[1]);
                float y = Float.valueOf(line.split(" ")[2]);
                float z = Float.valueOf(line.split(" ")[3]);
                vertices.add(new Vector3f(x, y, z));
            } else if (line.startsWith("vn ")) {
                float x = Float.valueOf(line.split(" ")[1]);
                float y = Float.valueOf(line.split(" ")[2]);
                float z = Float.valueOf(line.split(" ")[3]);
                normals.add(new Vector3f(x, y, z));
            } else if (line.startsWith("f ")) {
                Vector3f[] a = new Vector3f[3];
                Vector3f[] b = new Vector3f[3];
                a[0] = vertices.get(Integer.valueOf(line.split(" ")[1].split("//")[0]) - 1);
                a[1] = vertices.get(Integer.valueOf(line.split(" ")[2].split("//")[0]) - 1);
                a[2] = vertices.get(Integer.valueOf(line.split(" ")[3].split("//")[0]) - 1);
                b[0] = normals.get(Integer.valueOf(line.split(" ")[1].split("//")[1]) - 1);
                b[1] = normals.get(Integer.valueOf(line.split(" ")[2].split("//")[1]) - 1);
                b[2] = normals.get(Integer.valueOf(line.split(" ")[3].split("//")[1]) - 1);
                faces.add(new Face(a, b));
            }
        }
        br.close();
        m = new Model(faces);
        return m;
    }

}

型號類別:

package com.dryadengine.core;

import java.util.List;

/**
 *
 * @author Roy
 */
public class Model {

    private List<Face> faces;

    /**
     * Construct a new model object.
     * @param faces
     */
    public Model(List<Face> faces) {
        this.faces = faces;
    }

    /**
     * 
     * @return the faces list
     */
    public List<Face> getFaces() {
        return faces;
    }

}

臉型

package com.dryadengine.core;

import org.lwjgl.util.vector.Vector3f;

/**
 *
 * @author Roy
 */
public class Face {

    private Vector3f[] vertices;
    private Vector3f[] normals;

    public Face() {
        vertices = new Vector3f[3];
        normals = new Vector3f[3];
    }

    public Face(Vector3f[] vertices, Vector3f[] normals) {
        this();
        this.vertices = vertices;
        this.normals = normals;
    }

    /**
     * 
     * @return the vertices array
     */
    public Vector3f[] getVertices() {
        return vertices;
    }

    /**
     * 
     * @return the normals array
     */
    public Vector3f[] getNormals() {
        return normals;
    }

    /**
     * Sets the vertices array
     * @param vertices 
     */
    public void setVertices(Vector3f[] vertices) {
        this.vertices = vertices;
    }

    /**
     * Sets the normals array
     * @param normals 
     */
    public void setNormals(Vector3f[] normals) {
        this.normals = normals;
    }

}

頂點着色器:

#version 330

uniform mat4 mProjection;
uniform mat4 mView;
uniform mat4 mModel;

in vec4 vPosition;

void main()
{
    gl_Position = mProjection * mView * mModel * vPosition;
}

片段着色器:

#version 330

out vec4 vOutputColor;

void main()
{
    vOutputColor = vec4(1.0, 1.0, 1.0, 1.0);
}

我使用的bunny.obj文件: http ://rghost.net/54750078

是的,在這種情況下w將為1.0。 在OpenGL 3.3規范的2.8.1節(傳輸數組元素)的第一段中:

如果size為1,則該屬性的x分量由數組指定;否則,該值為0。 y,z和w分量分別隱式設置為0、0和1。 如果size為2,則屬性的x和y分量由數組指定; z和w分量分別隱式設置為0和1。 如果size為3,則指定x,y和z,w隱式設置為1。如果size為4,則指定所有分量。

通過查看您發布的代碼,我發現了一個將頂點坐標復制到vertexData

vertexData[i * 3 + j] = bunny.getFaces().get(i).getVertices()[j].x;
vertexData[i * 3 + j] = bunny.getFaces().get(i).getVertices()[j].y;
vertexData[i * 3 + j] = bunny.getFaces().get(i).getVertices()[j].z;

這會將x,y和z坐標復制到相同的數組位置。 它應該看起來像這樣:

vertexData[(i * 3 + j) * 3    ] = bunny.getFaces().get(i).getVertices()[j].x;
vertexData[(i * 3 + j) * 3 + 1] = bunny.getFaces().get(i).getVertices()[j].y;
vertexData[(i * 3 + j) * 3 + 2] = bunny.getFaces().get(i).getVertices()[j].z;

編輯:我想我發現了另一個問題。 經過更多研究LWJGL,看起來矩陣的轉換部分變成m30m31m32 因此,我相信您需要針對模型矩陣進行更改:

mView.m23 = -5;

對此:

mView.m32 = -5;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM