[英]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,看起來矩陣的轉換部分變成m30
, m31
, m32
。 因此,我相信您需要針對模型矩陣進行更改:
mView.m23 = -5;
對此:
mView.m32 = -5;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.