Related
I am currently trying to make an engine by using LWJGL3, and I am having issues trying to render a triangle.
I first make the window, make the window current context.
Then I make the renderer, which has the meshes.
Meshes have shaders attached to them. By init() the shaders compile and link.
Shader file (I have a parser, which takes fragment/vertex separately. The compilation completes without error, I do have error checking if it fails to compile).
#version 330
layout (location=0) in vec3 aPos;
layout (location=1) in vec4 aColor;
out vec4 fragment;
void main(){
fragment = aColor;
gl_Position = vec4(aPos,1.0);
}
//type fragment
#version 330
in vec4 fColor;
out vec4 color;
void main(){
color = fColor;
}
After this, I try to draw the mesh, it succeeds so, but in the window, I only get a gray color, which is a color I passed as an argument to start the window by that color.
Where could I be going wrong?
Mesh code:
package graphics;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.opengl.GL33.*;
public class Mesh {
int positionSize = 3;
int colorSize = 4;
int floatSizeInBytes = 4;
int vertexSizeInBytes = (positionSize + colorSize) * floatSizeInBytes;
private final Vertex[] vertices;
private final int[] indices;
private int vertexArrayObject;
private int vertexBufferObject;
private int elementArrayObject;
private int vertexCount;
private Shader shader;
public Mesh(Vertex[] vertices, int[] indices, Shader shader) {
this.shader = shader;
this.vertices = vertices;
this.indices = indices;
}
public void init(){
this.shader.compileAndLink();
this.shader.bind();
vertexCount = indices.length;
vertexArrayObject = glGenVertexArrays();
vertexBufferObject = glGenBuffers();
elementArrayObject = glGenBuffers();
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, flippedBuffer(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayObject);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, flippedBuffer(indices), GL_STATIC_DRAW);
glVertexAttribPointer(0, positionSize, GL_FLOAT, false, vertexSizeInBytes, 0);
glVertexAttribPointer(1, colorSize, GL_FLOAT, false, vertexSizeInBytes, (long) positionSize * floatSizeInBytes);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindVertexArray(0);
}
public void render() {
bind();
glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_INT, 0);
unbind();
System.out.println("Rendered");
}
public void clear() {
glDeleteBuffers(vertexBufferObject);
glDeleteVertexArrays(vertexArrayObject);
shader.unbind();
}
public void bind() {
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayObject);
}
public void unbind() {
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
public void stop() {
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);
shader.unbind();
}
public void setShader(Shader shader) {
try {
stop();
} catch (Exception e) {
System.out.println("Shader could not be stopped or not running");
e.printStackTrace();
}
this.shader = shader;
this.shader.bind();
}
public int getVertexArrayObject() {
return vertexArrayObject;
}
public int getVertexBufferObject() {
return vertexBufferObject;
}
public int getVertexCount() {
return vertexCount;
}
public int getElementArrayObject() {
return elementArrayObject;
}
public FloatBuffer flippedBuffer(Vertex[] vertices) {
FloatBuffer buffer = FloatBuffer.allocate(vertices.length * 7);
for (Vertex vertex : vertices) {
buffer.put(vertex.getPosition().coordinateArray());
buffer.put(vertex.getColor().coordinateArray());
}
buffer.flip();
return buffer;
}
public IntBuffer flippedBuffer(int[] elements) {
IntBuffer buffer = IntBuffer.allocate(elements.length);
for (int element : elements) {
buffer.put(element);
}
buffer.flip();
return buffer;
}
}
Shader code:
package graphics;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.lwjgl.opengl.GL33.*;
public class Shader {
private int shaderProgrammeID;
private String vertexSource;
private String fragmentSource;
private final String filePath;
public Shader(String filePath) {
this.filePath = filePath;
try {
String source = new String(Files.readAllBytes(Paths.get(filePath)));
String[] splitString = source.split("(//type)( )+([a-zA-Z]+)");
int index = source.indexOf("//type") + 6;
int endOfLine = source.indexOf("\r\n", index);
String firstPattern = source.substring(index, endOfLine).trim();
index = source.indexOf("//type", endOfLine) + 6;
endOfLine = source.indexOf("\r\n", index);
String secondPattern = source.substring(index, endOfLine).trim();
if (firstPattern.equals("vertex")) {
vertexSource = splitString[1];
} else if (firstPattern.equals("fragment")) {
fragmentSource = splitString[1];
} else {
throw new IOException("Unexpected shader type " + firstPattern + "'");
}
if (secondPattern.equals("vertex")) {
vertexSource = splitString[2];
} else if (secondPattern.equals("fragment")) {
fragmentSource = splitString[2];
} else {
throw new IOException("Unexpected shader type " + secondPattern + "'");
}
} catch (IOException e) {
e.printStackTrace();
assert false : "Error: Could not Open Shader" + filePath + "'";
}
}
public void compileAndLink() {
int vertexID;
int fragmentID;
vertexID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexID, vertexSource);
glCompileShader(vertexID);
if (glGetShaderi(vertexID, GL_COMPILE_STATUS) == GL_FALSE) {
System.out.println("ERROR: vertex shader - " + filePath + "could not be be compiled");
System.out.println(glGetShaderInfoLog(vertexID, glGetShaderi(vertexID, GL_INFO_LOG_LENGTH)));
assert false : "";
}
fragmentID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentID, fragmentSource);
glCompileShader(fragmentID);
if (glGetShaderi(fragmentID, GL_COMPILE_STATUS) == GL_FALSE) {
System.out.println("ERROR: fragment shader - " + filePath + "could not be be compiled");
System.out.println(glGetShaderInfoLog(fragmentID, glGetShaderi(fragmentID, GL_INFO_LOG_LENGTH)));
assert false : "";
}
this.shaderProgrammeID = glCreateProgram();
glAttachShader(this.shaderProgrammeID, vertexID);
glAttachShader(this.shaderProgrammeID, fragmentID);
glLinkProgram(this.shaderProgrammeID);
if (glGetProgrami(this.shaderProgrammeID, GL_LINK_STATUS) == GL_FALSE) {
System.out.println("ERROR: " + filePath + " shaders could not be linked");
System.out.println(glGetProgramInfoLog(this.shaderProgrammeID, glGetProgrami(fragmentID, GL_INFO_LOG_LENGTH)));
assert false : "";
}
System.out.println("Shader " + filePath + " compiled and linked successfully");
}
public void bind() {
glUseProgram(shaderProgrammeID);
}
public void unbind() {
glUseProgram(0);
}
}
Here is the renderer object, I use this to encapsulate Meshes to render them.
package graphics;
import java.util.HashSet;
import static org.lwjgl.opengl.GL33.*;
public class Renderer {
private final HashSet<Mesh> meshes;
public Renderer() {
meshes = new HashSet<>();
}
public void init() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (Mesh mesh : meshes) {
mesh.init();
}
}
public void render() {
clear();
for (Mesh mesh : meshes) {
mesh.render();
}
}
public void addMesh(Mesh mesh) {
meshes.add(mesh);
}
public void removeMesh(Mesh mesh) {
meshes.remove(mesh);
}
public void clear() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
public void destroy() {
for (Mesh mesh : meshes) {
mesh.unbind();
mesh.clear();
}
}
}
Engine code:
package core;
import graphics.Mesh;
import graphics.Renderer;
import io.Input;
import math.Vector4f;
import utils.Time;
public class Engine implements Runnable {
public static final int TARGET_FPS = 30;
private final Thread thread;
private final MainBehaviour behaviour;
private final Window window;
public Engine(Window window, MainBehaviour mainBehaviour) {
this.thread = new Thread(this, "loop");
this.window = window;
this.behaviour = mainBehaviour;
}
public void init() throws Exception {
Time.init(TARGET_FPS);
window.init();
behaviour.init();
}
public void start() {
thread.start();
}
#Override
public void run() {
try {
init();
loop();
clear();
} catch (Exception exception) {
exception.printStackTrace();
}
}
public void clear() {
behaviour.clear();
window.destroy();
}
private void update() {
behaviour.update();
/*Updating Time */
Time.updateFps();
Time.updateCycle();
/* Input handling */
Input.update();
window.update();
}
private void render() {
behaviour.render(window);
}
public void loop() {
while (window.isRunning()) {
/* Updating delta Time for correct interval Calculation */
Time.updateDeltaTime();
/* Rendering and actually updating Game */
while (Time.checkCycle()) {
update();
}
render();
System.out.println(Time.getFps());
if (!window.isVSync()) {
Time.sync();
}
}
}
}
Window code:
package core;
import graphics.Renderer;
import io.Input;
import math.Vector4f;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11C.*;
import static org.lwjgl.system.MemoryUtil.NULL;
public class Window {
private final Vector4f color;
private int height;
private int width;
private long window;
private long monitor;
private boolean isFullScreen;
private boolean isVSync;
private String name;
private GLFWVidMode mode;
private final Renderer renderer;
public Window(int width, int height, String name, Vector4f color, boolean isVSync, Renderer renderer) {
this.height = height;
this.width = width;
this.name = name;
this.color = color;
this.isVSync = isVSync;
this.renderer = renderer;
}
public Window(int width, int height, String name, String monitor, Vector4f color, Renderer renderer) {
this.height = height;
this.width = width;
this.name = name;
this.color = color;
if (monitor.equals("primary")) {
this.monitor = glfwGetPrimaryMonitor();
mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
}
this.renderer = renderer;
}
public Renderer getRenderer() {
return renderer;
}
public boolean isVSync() {
return isVSync;
}
public void setVSync(boolean vSync) {
this.isVSync = vSync;
}
public boolean isFullScreen() {
return isFullScreen;
}
public void setFullScreen(boolean fullScreen) {
isFullScreen = fullScreen;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void init() {
if (!glfwInit()) {
throw new IllegalStateException("GLFW not initialized or initialization failed");
} else {
GLFWErrorCallback.createPrint(System.err).set();
try {
if (monitor != NULL) {
this.monitor = glfwGetPrimaryMonitor();
mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
window = glfwCreateWindow(width, height, name, glfwGetPrimaryMonitor(), NULL);
isFullScreen = true;
} else {
window = glfwCreateWindow(width, height, name, NULL, NULL);
}
if (window == NULL) {
throw new IllegalStateException("Failed to create the GLFW window");
}
} catch (RuntimeException e) {
System.out.println(e.getMessage());
}
}
GLFWErrorCallback.createPrint(System.err).set();
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwMakeContextCurrent(this.window);
GL.createCapabilities();
glfwShowWindow(window);
Input.init();
setupCallback();
renderer.init();
}
private void setupCallback() {
glfwSetKeyCallback(window, Input.getKeyboard());
glfwSetMouseButtonCallback(window, Input.getMbtn());
glfwSetCursorPosCallback(window, Input.getMouse());
}
public void destroy() {
renderer.destroy();
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
glfwTerminate();
}
public void setWindowed(int width, int height, int x, int y) {
glfwSetWindowMonitor(window, NULL, x, y, width, height, mode.refreshRate());
}
public void fullScreenWindow() {
glfwSetWindowMonitor(window, NULL, 0, 0, mode.width(), mode.height(), mode.refreshRate());
}
public void fullScreen() {
glfwSetWindowMonitor(window, monitor, 0, 0, mode.width(), mode.height(), 0);
}
public void update() {
if (!isRunning()) {
destroy();
return;
}
renderer.render();
clear();
glfwSwapBuffers(window);
glfwPollEvents();
}
public void clear() {
glClearColor(color.x, color.y, color.z, color.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
public boolean isRunning() {
return !glfwWindowShouldClose(window);
}
}
I render in update()
And the main class where I call the whole thing to run:
import core.Engine;
import core.MainBehaviour;
import core.Window;
import graphics.Mesh;
import graphics.Renderer;
import graphics.Shader;
import graphics.Vertex;
import io.Input;
import math.Vector3f;
import math.Vector4f;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_SPACE;
public class Preview {
public static void main(String[] args) {
MainBehaviour game = new MainBehaviour() {
#Override
public void init() throws Exception {
}
#Override
public void update() {
if (Input.isKeyDown(GLFW_KEY_SPACE))
System.out.println("Space button pushed");
}
#Override
public void render(Window window) {
}
#Override
public void clear() {
}
};
Vertex[] vertices = new Vertex[]{
new Vertex(new Vector3f(-1f, -1f, 0f), new Vector4f(1f, 0f, 0f, 1f)),
new Vertex(new Vector3f(0f, 1f, 0f), new Vector4f(0f, 1f, 0f, 1f)),
new Vertex(new Vector3f(1f, -1f, 0f), new Vector4f(0f, 0f, 1f, 1f)),
};
int[] indices = new int[]{
0, 1, 2
};
Shader shader = new Shader("res/shaders/default.glsl");
Mesh mesh = new Mesh(vertices, indices, shader);
Renderer renderer = new Renderer();
renderer.addMesh(mesh);
Window window = new Window(500, 500, "Preview", new Vector4f(0.5f, 0.5f, 0.5f, 1f), false, renderer);
Engine engine = new Engine(window, game);
engine.run();
}
}
The vertex shader color output name is fragment, but the fragment shader input name is fColor. The interface is linked by name. You must use the same name on both sides of the interface. Change the vertex shader:
#version 330
layout (location=0) in vec3 aPos;
layout (location=1) in vec4 aColor;
out vec4 fColor;
void main(){
fColor = aColor;
gl_Position = vec4(aPos,1.0);
}
You seem to be clearing the buffer right after rendering the triangle and before swapping the buffer's contents to screen.
In your window code:
...
renderer.render();
clear();
glfwSwapBuffers(window);
...
You clear the buffer's contents right before swapping it to the window instead of clearing before rendering:
...
clear();
renderer.render();
glfwSwapBuffers(window);
...
I am trying to render a 2D square, but my program crashes. I think my order of methods is incorrect. I am using LWJGL3, with the jars Lwjgl, GLFW, and OpenGL. The stacktrace shows the error is an EXCEPTION_ACCESS_VIOLATION, and the error is at the first openGL function depending on which one is first (with current code it is GL20.glGetAttribLocation() (following the guid here: https://github.com/SilverTiger/lwjgl3-tutorial/wiki/Rendering)
I am also not using legacyGL
If your having this problem:
add the lines GLFW.makeContextCurrent(window) and Gl.createCapabilities()
Main:
public class DungeonRunners {
private double lastTick;
private float timeCount;
private int fps;
private int fpsCount;
private int ups;
private int upsCount;
public static void main(String[] args) {
System.out.println("LWJGL Version: " + Version.getVersion());
int width = 1240;
int height = 720;
boolean legacyGL = false;
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if(arg.equals("width:")) {
try {
width = Integer.parseInt(args[i+1]);
i++;
} catch (NumberFormatException ignored) { }
} else if(arg.equals("height:")) {
try {
height = Integer.parseInt(args[i+1]);
} catch (NumberFormatException ignored) { }
} else if(arg.equals("-useLegacyGL")) {
legacyGL = true;
}
}
DungeonRunners dungeonRunners = new DungeonRunners();
dungeonRunners.start(width, height, legacyGL);
}
private void start(int width, int height, Boolean legacyGL) {
long window;
GLFW.glfwInit();
if(!legacyGL) {
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
window = GLFW.glfwCreateWindow(width, height, "Dungeon Runners", MemoryUtil.NULL, MemoryUtil.NULL);
} else {
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 2);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 1);
window = GLFW.glfwCreateWindow(width, height, "Dungeon Runners", MemoryUtil.NULL, MemoryUtil.NULL);
}
RenderEngine engine = new RenderEngine(legacyGL);
while(!GLFW.glfwWindowShouldClose(window)) {
update();
engine.frame();
}
}
private void update() {
if (timeCount > 1f) {
fps = fpsCount;
fpsCount = 0;
ups = upsCount;
upsCount = 0;
timeCount -= 1f;
}
}
private float getDelta() {
double time = getTime();
float delta = (float) (time - lastTick);
lastTick = time;
timeCount += delta;
return delta;
}
public double getTime() {
return System.nanoTime() / 1000000000.0;
}
private void updateFPS() {
fpsCount++;
}
private void updateUPS() {
upsCount++;
}
}
The code is pretty explanatory, here is my RenderEngine class:
public class RenderEngine {
private int shaderProgram;
public RenderEngine(Boolean legacyGL) {
setVertexAttribs();
bindImage();
int vao = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vao);
setupShaders(legacyGL);
GL20.glUseProgram(shaderProgram);
setUniformVars();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
}
private void bindImage() {
try (MemoryStack stack = MemoryStack.stackPush()) {
FloatBuffer vertices = stack.mallocFloat(3 * 6);
vertices.put(-0.6f).put(-0.4f).put(0f).put(1f).put(0f).put(0f);
vertices.put(0.6f).put(-0.4f).put(0f).put(0f).put(1f).put(0f);
vertices.put(0f).put(0.6f).put(0f).put(0f).put(0f).put(1f);
vertices.flip();
int vbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
MemoryStack.stackPop();
}
}
public void frame() {
}
private void setUniformVars() {
int uniModel = GL20.glGetUniformLocation(shaderProgram, "model");
UtilMatrix4f model = new UtilMatrix4f();
GL20.glUniformMatrix4fv(uniModel, false, model.getBuffer());
int uniView = GL20.glGetUniformLocation(shaderProgram, "view");
UtilMatrix4f view = new UtilMatrix4f();
GL20.glUniformMatrix4fv(uniView, false, view.getBuffer());
int uniProjection = GL20.glGetUniformLocation(shaderProgram, "projection");
float ratio = 640f / 480f;
UtilMatrix4f projection = UtilMatrix4f.orthographic(-ratio, ratio, -1f, 1f, -1f, 1f);
GL20.glUniformMatrix4fv(uniProjection, false, projection.getBuffer());
}
private void setVertexAttribs() {
int floatSize = 4;
int posAttrib = GL20.glGetAttribLocation(shaderProgram, "position");
GL20.glEnableVertexAttribArray(posAttrib);
GL20.glVertexAttribPointer(posAttrib, 3, GL11.GL_FLOAT, false, 6 * floatSize, 0);
int colAttrib = GL20.glGetAttribLocation(shaderProgram, "color");
GL20.glEnableVertexAttribArray(colAttrib);
GL20.glVertexAttribPointer(colAttrib, 3, GL11.GL_FLOAT, false, 6 * floatSize, 3 * floatSize);
}
private void setupShaders(boolean legacyGL) {
int vertexShader = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
if(legacyGL)
GL20.glShaderSource(vertexShader, "src\\main\\java\\bigbade\\dungeonrunners\\renderer\\shaders\\legacyVertexShader.txt");
else
GL20.glShaderSource(vertexShader, "src\\main\\java\\bigbade\\dungeonrunners\\renderer\\shaders\\vertexShader.txt");
GL20.glCompileShader(vertexShader);
int status = GL20.glGetShaderi(vertexShader, GL20.GL_COMPILE_STATUS);
if (status != GL11.GL_TRUE) {
throw new RuntimeException(GL20.glGetShaderInfoLog(vertexShader));
}
int fragmentShader = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
if(legacyGL)
GL20.glShaderSource(vertexShader, "src\\main\\java\\bigbade\\dungeonrunners\\renderer\\shaders\\legacyFragmentShader.txt");
else
GL20.glShaderSource(fragmentShader, "src\\main\\java\\bigbade\\dungeonrunners\\renderer\\shaders\\fragmentShader.txt");
GL20.glCompileShader(fragmentShader);
status = GL20.glGetShaderi(fragmentShader, GL20.GL_COMPILE_STATUS);
if (status != GL11.GL_TRUE) {
throw new RuntimeException(GL20.glGetShaderInfoLog(fragmentShader));
}
shaderProgram = GL20.glCreateProgram();
GL20.glAttachShader(shaderProgram, vertexShader);
GL20.glAttachShader(shaderProgram, fragmentShader);
GL30.glBindFragDataLocation(shaderProgram, 0, "fragColor");
GL20.glLinkProgram(shaderProgram);
status = GL20.glGetProgrami(shaderProgram, GL20.GL_LINK_STATUS);
if (status != GL11.GL_TRUE) {
throw new RuntimeException(GL20.glGetProgramInfoLog(shaderProgram));
}
}
}
I am new at openGL
I created this skybox on LWJGL but It's all black
SkyboxRenderer Class :
private static String[] TEXTURE_FILES = {"right","left","bottom","back","front"};
private RawModel cube;
private int texture;
private SkyboxShader shader;
public SkyboxRenderer(Loader loader, Matrix4f projectionMatirx) {
cube = loader.loadToVAO(VERTICES, 3);
texture = loader.loadCubeMap(TEXTURE_FILES);
shader = new SkyboxShader();
shader.start();
shader.loadProjectionMatrix(projectionMatirx);
shader.stop();
}
public void render(Camera camera){
shader.start();
shader.loadViewMatrix(camera);
GL30.glBindVertexArray(cube.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texture);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, cube.getVertexCount());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
shader.stop();
}
Loader loadCubeMap function :
public int loadCubeMap(String[] textureFiles){
int texID = GL11.glGenTextures();
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texID);
for(int i = 0; i < textureFiles.length;i++){
TextureData data = decodeTextureFile("res/" + textureFiles[i] + ".png");
GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL11.GL_RGBA, data.getWidth(), data.getHeight(), 0, GL11.GL_RGBA,
GL11.GL_UNSIGNED_BYTE, data.getBuffer());
}
GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
textures.add(texID);
return texID;
}
private TextureData decodeTextureFile(String fileName) {
int width = 0;
int height = 0;
ByteBuffer buffer = null;
try {
FileInputStream in = new FileInputStream(fileName);
PNGDecoder decoder = new PNGDecoder(in);
width = decoder.getWidth();
height = decoder.getHeight();
buffer = ByteBuffer.allocateDirect(4 * width * height);
decoder.decode(buffer, width * 4, Format.RGBA);
buffer.flip();
in.close();
} catch (Exception e) {
e.printStackTrace();
System.err.println("Tried to load texture " + fileName + ", didn't work");
System.exit(-1);
}
return new TextureData(buffer, width, height);
}
Textures exist, but skybox is fullyblack can someone help me!
How can i fix it
I need to add more details for posting because there is too much code...
SkyboxShader :
public class SkyboxShader extends ShaderProgram{
private static final String VERTEX_FILE = "src/com/redcatengine/skybox/skyboxVertexShader.txt";
private static final String FRAGMENT_FILE = "src/com/redcatengine/skybox/skyboxFragmentShader.txt";
private int location_projectionMatrix;
private int location_viewMatrix;
public SkyboxShader() {
super(VERTEX_FILE, FRAGMENT_FILE);
}
public void loadProjectionMatrix(Matrix4f matrix){
super.loadMatrix(location_projectionMatrix, matrix);
}
public void loadViewMatrix(Camera camera){
Matrix4f matrix = Maths.createViewMatrix(camera);
matrix.m30 = 0;
matrix.m31 = 0;
matrix.m32 = 0;
super.loadMatrix(location_viewMatrix, matrix);
}
#Override
protected void getAllUniformLocations() {
location_projectionMatrix = super.getUniformLocation("projectionMatrix");
location_viewMatrix = super.getUniformLocation("viewMatrix");
}
#Override
protected void bindAttributes() {
super.bindAttribute(0, "position");
}
}
public abstract class ShaderProgram {
private int programID;
private int vertexShaderID;
private int fragmentShaderID;
private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
public ShaderProgram(String vertexFile, String fragmentFile) {
vertexShaderID = loadShader(vertexFile, GL20.GL_VERTEX_SHADER);
fragmentShaderID = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER);
programID = GL20.glCreateProgram();
GL20.glAttachShader(programID, vertexShaderID);
GL20.glAttachShader(programID, fragmentShaderID);
bindAttributes();
GL20.glLinkProgram(programID);
GL20.glValidateProgram(programID);
getAllUniformLocations();
}
protected abstract void getAllUniformLocations();
protected int getUniformLocation(String uniformName){
return GL20.glGetUniformLocation(programID, uniformName);
}
public void start(){
GL20.glUseProgram(programID);
}
public void stop(){
GL20.glUseProgram(0);
}
public void cleanUp(){
stop();
GL20.glDetachShader(programID, vertexShaderID);
GL20.glDetachShader(programID, fragmentShaderID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
GL20.glDeleteProgram(programID);
}
protected abstract void bindAttributes();
protected void bindAttribute(int attribute, String variableName){
GL20.glBindAttribLocation(programID, attribute, variableName);
}
protected void loadInt(int location, int value){
GL20.glUniform1i(location, value);
}
protected void loadFloat(int location, float value){
GL20.glUniform1f(location, value);
}
protected void loadVector(int location, Vector3f value){
GL20.glUniform3f(location, value.x, value.y, value.z);
}
protected void load2DVector(int location, Vector2f value){
GL20.glUniform2f(location, value.x, value.y);
}
protected void loadBoolean(int location, boolean value){
float toLoad = 0;
if(value)toLoad = 1;else toLoad = 0;
GL20.glUniform1f(location, toLoad);
}
protected void loadMatrix(int location, Matrix4f matrix){
matrix.store(matrixBuffer);
matrixBuffer.flip();
GL20.glUniformMatrix4(location, false, matrixBuffer);
}
private static int loadShader(String file, int type){
StringBuilder shaderSource = new StringBuilder();
try{
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine()) != null){
shaderSource.append(line).append("\n");
}
reader.close();
}catch(IOException e){
System.err.println("Could not read shader file!");
e.printStackTrace();
System.exit(-1);
}
int shaderID = GL20.glCreateShader(type);
GL20.glShaderSource(shaderID, shaderSource);
GL20.glCompileShader(shaderID);
if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS)==GL11.GL_FALSE){
System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
System.out.println("Could not compile shader.");
System.exit(-1);
}
return shaderID;
}
}
skyboxFragmentShader :
#version 400
in vec3 textureCoords;
out vec4 out_Color;
uniform samplerCube cubeMap;
void main(void){
out_Color = texture(cubeMap, textureCoords);
}
skyboxVertexShader
#version 400
in vec3 position;
out vec3 textureCoords;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
void main(void){
gl_Position = projectionMatrix * viewMatrix * vec4(position, 1.0);
textureCoords = position;
}`
Your cube map texture is not cube complete:
Your loader code iterates over all files in the array it is called with:
for(int i = 0; i < textureFiles.length;i++){
// [...]
GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, [...])
}
However, your input array contains only 5 entires:
String[] TEXTURE_FILES = {"right","left","bottom","back","front"};
You provide only 5 faces for the cube, and forgot the "top" face.
According to the GL spec (quotes are from section 8.17 of the OpenGL 4.5 core profile specification),
A cube map texture is mipmap complete if each of the six texture
images, considered individually, is mipmap complete. Additionally, a
cube map texture is cube complete if the following conditions all hold
true:
The level_base texture images of each of the six cube map faces have identical, positive, and square dimensions.
The levelbase
images were each specified with the same internal format.
It further goes on define texture completeness:
Using the preceding definitions, a texture is complete unless any of the following
conditions hold true:
[...]
The texture is a cube map texture, and is not cube complete.
[...]
So your cube map texture is not complete.
Section 11.1.3.5 states:
If a sampler is used in a shader and the sampler’s associated texture is not
complete, as defined in section 8.17, (0; 0; 0; 1) will be returned for a non-shadow sampler and 0 for a shadow sampler.
So indeed, your cube map should appear completely black.
I am rendering a simple quad and have been experimenting with shaders. It worked fine, but I followed a texturing tutorial to add textures and I must have changed something. Because now, even though all the texturing code is commented out, the quad doesn't render when I turn shaders on. I suspect it has something to do with the data binding, as I am still trying to learn it. I can't for the life of me find what's wrong!
Shaders (vertex and fragment):
//vertex
#version 400 core
in vec3 position;
out vec3 colour;
void main (void) {
colour = vec3(position.x + 0.5, 1.0, position.y + 0.5);
}
//fragment
#version 400 core
in vec3 colour;
out vec4 out_Colour;
void main (void) {
out_Colour = vec4(colour, 1.0);
}
Shader program:
public abstract class ShaderProgram {
private int programId;
private int vertexId;
private int fragmentId;
public ShaderProgram (String vertexFile, String fragmentFile) {
vertexId = loadShader(vertexFile, GL20.GL_VERTEX_SHADER);
fragmentId = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER);
programId = GL20.glCreateProgram();
GL20.glAttachShader(programId, vertexId);
GL20.glAttachShader(programId, fragmentId);
bindAttributes();
GL20.glLinkProgram(programId);
GL20.glValidateProgram(programId);
}
public void start () {
GL20.glUseProgram(programId);
}
public void stop () {
GL20.glUseProgram(0);
}
public void cleanUp () {
stop();
GL20.glDetachShader(programId, vertexId);
GL20.glDetachShader(programId, fragmentId);
GL20.glDeleteShader(vertexId);
GL20.glDeleteShader(fragmentId);
GL20.glDeleteProgram(programId);
}
protected abstract void bindAttributes ();
protected void bindAttribute (int attribute, String variableName) {
GL20.glBindAttribLocation(programId, attribute, variableName);
}
private static int loadShader (String file, int type) {
StringBuilder shaderSource = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
while ((line = reader.readLine()) != null) {
shaderSource.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
System.err.println("Could not read shader file!");
e.printStackTrace();
System.exit(-1);
}
int shaderId = GL20.glCreateShader(type);
GL20.glShaderSource(shaderId, shaderSource);
GL20.glCompileShader(shaderId);
if (GL20.glGetShaderi(shaderId, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
System.err.println(GL20.glGetShaderInfoLog(shaderId));
System.err.println("Could not compile shader!");
System.exit(-1);
}
return shaderId;
}
}
Main shader (extends Shader program):
public class MainShader extends ShaderProgram {
private static final String VERTEX_FILE = "src/shaders/vertexShader.txt";
private static final String FRAGMENT_FILE = "src/shaders/fragmentShader.txt";
public MainShader() {
super(VERTEX_FILE, FRAGMENT_FILE);
}
#Override
protected void bindAttributes() {
super.bindAttribute(ModelLoader.VERTEX_INDICE, "position");
//super.bindAttribute(1, "uv");
}
}
Model loader:
public class ModelLoader {
private static List<Integer> vaos = new ArrayList<Integer>();
private static List<Integer> vbos = new ArrayList<Integer>();
private static List<Integer> textures = new ArrayList<Integer>();
public static final int VERTEX_INDICE = 0;
public static final int UV_INDICE = 1;
public static RawModel loadToVAO (float[] positions, int[] indices) {
int vaoId = createVAO();
bindIndicesBuffer(indices);
storeDataInAttributeList(VERTEX_INDICE, 3, positions);
//storeDataInAttributeList(UV_INDICE, 2, uvCoords);
unbindVAO();
return new RawModel(vaoId, indices.length);
}
/*public static int loadTexture (String file, int textureUnit) {
try {
return TextureLoader.loadTexture("rsrc/" + file + ".png", GL11.GL_TEXTURE_2D);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}*/
public static int loadTexture(String file, int textureUnit) {
String filename = "rsrc/" + file + ".png";
ByteBuffer buf = null;
int tWidth = 0;
int tHeight = 0;
try {
// Open the PNG file as an InputStream
InputStream in = new FileInputStream(filename);
// Link the PNG decoder to this stream
PNGDecoder decoder = new PNGDecoder(in);
// Get the width and height of the texture
tWidth = decoder.getWidth();
tHeight = decoder.getHeight();
// Decode the PNG file in a ByteBuffer
buf = ByteBuffer.allocateDirect(
4 * decoder.getWidth() * decoder.getHeight());
decoder.decode(buf, decoder.getWidth() * 4, Format.RGBA);
buf.flip();
in.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
// Create a new texture object in memory and bind it
int texId = GL11.glGenTextures();
GL13.glActiveTexture(textureUnit);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texId);
// All RGB bytes are aligned to each other and each component is 1 byte
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
// Upload the texture data and generate mip maps (for scaling)
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, tWidth, tHeight, 0,
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
// Setup the ST coordinate system
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
// Setup what to do when the texture has to be scaled
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
GL11.GL_LINEAR_MIPMAP_LINEAR);
return texId;
}
private static int createVAO () {
int vaoId = GL30.glGenVertexArrays();
vaos.add(vaoId);
GL30.glBindVertexArray(vaoId);
return vaoId;
}
private static void bindIndicesBuffer (int[] indices) {
int vbo = GL15.glGenBuffers();
vbos.add(vbo);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vbo);
IntBuffer buffer = storeDataInIntBuffer(indices);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
}
public static void cleanUp () {
for (int vao : vaos) {
GL30.glDeleteVertexArrays(vao);
}
for (int vbo : vbos) {
GL15.glDeleteBuffers(vbo);
}
for (int texture : textures) {
GL11.glDeleteTextures(texture);
}
}
private static void storeDataInAttributeList (int attributeNumber, int size, float[] data) {
int vboId = GL15.glGenBuffers();
vbos.add(vboId);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
FloatBuffer buffer = storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(attributeNumber, size, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private static void unbindVAO () {
GL30.glBindVertexArray(0);
}
private static IntBuffer storeDataInIntBuffer (int[] data) {
IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
private static FloatBuffer storeDataInFloatBuffer (float[] data) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
I had forgotten to assign gl_Position in the vertex shader.
Hello I wan't to do heightmap based game and I have optimization problem. I acctualy rendering in DisplayList but when I want to render heightmap 512x512 I have only 20-30 fps. I tried something in vbo but that don't work. Here is my sourcecode to display lists rendering:
public class Heightmap {
public static final Vector2f CHUNK_XZ = new Vector2f(256, 256);
public int CHUNK_ID;
private float[][] chunk_data = null;
private Vector3f[][] chunk_color_data = null;
private Vector3f pos;
private Vector3f scale = new Vector3f(10, 10, 10);
private boolean visible = true;
private int displayID;
private Texture texture;
public Heightmap(Vector3f pos) {
this.pos = pos;
chunk_data = new float[(int) CHUNK_XZ.x][(int) CHUNK_XZ.y];
chunk_color_data = new Vector3f[(int) CHUNK_XZ.x][(int) CHUNK_XZ.y];
for(int x = 0; x < chunk_data.length; x++) {
for(int y = 0; y < chunk_data[0].length; y++) {
chunk_data[x][y] = 1.0f;
chunk_color_data[x][y] = new Vector3f(0f, 0f, (float) Math.random());
}
}
try {
texture = TextureLoader.getTexture("jpg", new FileInputStream(new File("grassy.jpg")));
} catch (IOException e) {
e.printStackTrace();
}
displayID = glGenLists(1);
GL11.glNewList(displayID, GL11.GL_COMPILE);
texture.bind();
GL11.glPushMatrix();
GL11.glScalef(scale.x, scale.y, scale.z);
GL11.glBegin(GL11.GL_QUADS);
int heightmapExaggeration = 10;
for(int x=0; x < chunk_data.length; x++) {
for(int y=0; y < chunk_data[x].length; y++) {
GL11.glColor3f(chunk_color_data[x][y].getX(), chunk_color_data[x][y].getY(), chunk_color_data[x][y].getZ());
GL11.glTexCoord2f(0, 0);
GL11.glVertex3f(x*0.25f, getHeightAt(x, y)*heightmapExaggeration, y*0.25f);
GL11.glTexCoord2f(1, 0);
GL11.glVertex3f((x+1)*0.25f, getHeightAt(x+1, y)*heightmapExaggeration, y*0.25f);
GL11.glTexCoord2f(1, 1);
GL11.glVertex3f((x+1)*0.25f, getHeightAt(x+1, y+1)*heightmapExaggeration, (y+1)*0.25f);
GL11.glTexCoord2f(0, 1);
GL11.glVertex3f(x*0.25f, getHeightAt(x, y+1)*heightmapExaggeration, (y+1)*0.25f);
}
}
GL11.glEnd();
GL11.glPopMatrix();
texture.release();
GL11.glEndList();
}
public Chunk(float[][] chunk_data, Vector3f[][] chunk_color_data, Vector3f pos) {
this.chunk_data = chunk_data;
this.chunk_color_data = chunk_color_data;
this.pos = pos;
try {
texture = TextureLoader.getTexture("jpg", new FileInputStream(new File("grassy.jpg")));
} catch (IOException e) {
e.printStackTrace();
}
displayID = glGenLists(1);
GL11.glNewList(displayID, GL11.GL_COMPILE);
texture.bind();
GL11.glPushMatrix();
GL11.glScalef(scale.x, scale.y, scale.z);
GL11.glBegin(GL11.GL_QUADS);
int heightmapExaggeration = 10;
for(int x=0; x < chunk_data.length; x++){
for(int y=0; y < chunk_data[x].length; y++){
GL11.glColor3f(chunk_color_data[x][y].getX(), chunk_color_data[x][y].getY(), chunk_color_data[x][y].getZ());
GL11.glTexCoord2f(0, 0);
GL11.glVertex3f(x*0.25f, getHeightAt(x, y)*heightmapExaggeration, y*0.25f);
GL11.glTexCoord2f(1, 0);
GL11.glVertex3f((x+1)*0.25f, getHeightAt(x+1, y)*heightmapExaggeration, y*0.25f);
GL11.glTexCoord2f(1, 1);
GL11.glVertex3f((x+1)*0.25f, getHeightAt(x+1, y+1)*heightmapExaggeration, (y+1)*0.25f);
GL11.glTexCoord2f(0, 1);
GL11.glVertex3f(x*0.25f, getHeightAt(x, y+1)*heightmapExaggeration, (y+1)*0.25f);
}
}
GL11.glEnd();
GL11.glPopMatrix();
texture.release();
GL11.glEndList();
}
public float getHeightAt(int x, int z){
try {
return chunk_data[x][z];
} catch(Exception e) {
return 0;
}
}
public void render() {
glPushMatrix();
glTranslatef(pos.x, pos.y, pos.z);
glCallList(displayID);
glPopMatrix();
}
public void setChunkDataAtCoords(int x, int y, float value) {
this.chunk_data[x][y] = value;
}
public float[][] getChunk_data() {
return chunk_data;
}
public Vector3f[][] getChunk_color_data() {
return chunk_color_data;
}
public Vector3f getPos() {
return pos;
}
public Vector3f getScale() {
return scale;
}
public void setChunk_data(float[][] chunk_data) {
this.chunk_data = chunk_data;
}
public void setChunk_color_data(Vector3f[][] chunk_color_data) {
this.chunk_color_data = chunk_color_data;
}
public void setChunkColorDataAtCoords(int x, int y, Vector3f color) {
chunk_color_data[x][y] = color;
}
public void setPos(Vector3f pos) {
this.pos = pos;
}
public void setScale(Vector3f scale) {
this.scale = scale;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
}
And vbo rendering code but that don't work properly:
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
public class Terrain {
private int width = 200;
private int height = 200;
private int verticies = (3*(2*height)*width);
private int indicies = ((height*2)*width);
private FloatBuffer vBuffer = BufferUtils.createFloatBuffer(verticies);
private IntBuffer iBuffer = BufferUtils.createIntBuffer(indicies);
private IntBuffer ib = BufferUtils.createIntBuffer(indicies);
private static float[][] data;
public Terrain() {
glPushMatrix();
glScalef(0.6f, 0.6f, 0.6f);
glTranslatef(0f, 10f, 0f);
loadHeightImage();
loadHeightVerticies();
drawHeightMap();
glPopMatrix();
}
public void loadHeightImage() {
try {
BufferedImage heightmapImage = ImageIO.read(new File("height.jpg"));
data = new float[heightmapImage.getWidth()][heightmapImage.getHeight()];
Color colour;
for (int x = 0; x < data.length; x++)
{
for (int z = 0; z < data[x].length; z++)
{
colour = new Color(heightmapImage.getRGB(x, z));
data[z][x] = colour.getRed();
}
}
} catch (IOException e){
e.printStackTrace();
}
}
public void loadHeightVerticies() {
for (int z = 0; z < this.data.length - 1; z++) {
for (int x = 0; x < this.data[z].length; x++) {
vBuffer.put(x).put(this.data[z][x]).put(z);
vBuffer.put(x).put(this.data[z + 1][x]).put(z + 1);
}
}
this.vBuffer.flip();
for (int n = 0; n < indicies; n++) {
this.iBuffer.put( n);
}
this.iBuffer.flip();
}
public void drawHeightMap() {
glGenBuffers(ib);
int vHandle = ib.get(0);
int iHandle = ib.get(1);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vHandle);
glBufferData(GL_ARRAY_BUFFER, vBuffer, GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, 0L);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iBuffer, GL_STATIC_DRAW);
for (int x = 0; x < 400; x++) {
glDrawElements(GL_TRIANGLE_STRIP, 400, GL_UNSIGNED_SHORT, 1600 * x);
}
glDisableClientState(GL_VERTEX_ARRAY);
ib.put(0, vHandle);
glDeleteBuffers(ib);
}
}
And one more question how can I color heightmap like in the displaylist mode ? Sorry for my English.
How many chunks are you rendering? Maybe you should look at face culling if you don't need all sides of the quads.