I am modeling a 3D maze in Java OpenGL (JOGL) and I am facing an issue about lights. No matter how hard I try lights don't act the way I want to.
This is setup in init method (which is called when the window is created):
// nastaveni materialu - difusni slozka
float[] mat_dif = new float[] { 0.3f, 0.3f, 0.3f, 0.3f };
// nastaveni materialu - zrcadlova slozka
float[] mat_spec = new float[] { 1, 1, 1, 1 };
// nastaveni materialu - ambientni slozka
float[] mat_amb = new float[] { 0.3f, 0.3f, 0.3f, 0.3f };
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, mat_amb, 0);
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, mat_dif, 0);
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, mat_spec, 0);
//nastaveni bileho svetla
float[] lightWhite = new float[] { 1, 1, 1, 1 };
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT_AND_DIFFUSE, lightWhite, 0);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_SPECULAR, lightWhite, 0);
//nastaveni cerveneho
float[] lightRed = new float[] { 1, 0, 0, 1 };
gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_AMBIENT_AND_DIFFUSE, lightRed, 0);
gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_SPECULAR, lightRed, 0);
//nastaveni modreho
float[] lightBlue = new float[] { 0, 0, 1, 1 };
gl.glLightfv(GL2.GL_LIGHT2, GL2.GL_AMBIENT_AND_DIFFUSE, lightBlue, 0);
gl.glLightfv(GL2.GL_LIGHT2, GL2.GL_SPECULAR, lightBlue, 0);
and code in display method (called when each frame is rendered)
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
light_position = new float[] {6.0f, 2.0f, -6.0f, 1.0f};// bod v prostoru
light_direction = new float[] {0.0f, 0.0f, -6.0f, 0.0f};
light_position2 = new float[] {8.0f, 2.0f, -7.0f, 1.0f};// bod v prostoru
light_direction2 = new float[] {15.0f, 0.0f, -7.0f, 0.0f};
light_position3 = new float[] {8.0f, 2.0f, -4.0f, 1.0f};// bod v prostoru
light_direction3 = new float[] {8.0f, 0.0f, 0.0f, 0.0f};
gl.glPushMatrix();
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, light_position, 0);
gl.glLightf(GL2.GL_LIGHT0,GL2.GL_SPOT_CUTOFF,60.0f);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_SPOT_DIRECTION, light_direction, 0);
gl.glLightf(GL2.GL_LIGHT0,GL2.GL_SPOT_EXPONENT,10.0f);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, light_position2, 0);
gl.glLightf(GL2.GL_LIGHT1,GL2.GL_SPOT_CUTOFF,60.0f);
gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_SPOT_DIRECTION, light_direction2, 0);
gl.glLightf(GL2.GL_LIGHT1,GL2.GL_SPOT_EXPONENT,10.0f);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glLightfv(GL2.GL_LIGHT2, GL2.GL_POSITION, light_position3, 0);
gl.glLightf(GL2.GL_LIGHT2,GL2.GL_SPOT_CUTOFF,35.0f);
gl.glLightfv(GL2.GL_LIGHT2, GL2.GL_SPOT_DIRECTION, light_direction3, 0);
gl.glLightf(GL2.GL_LIGHT2,GL2.GL_SPOT_EXPONENT,10.0f);
gl.glPopMatrix();
gl.glColorMaterial (GL2.GL_FRONT_AND_BACK,
GL2.GL_AMBIENT_AND_DIFFUSE ) ;
gl.glEnable(GL2.GL_COLOR_MATERIAL);
gl.glEnable(GL2.GL_LIGHTING);
gl.glEnable(GL2.GL_LIGHT0);
gl.glEnable(GL2.GL_LIGHT1);
gl.glEnable(GL2.GL_LIGHT2);
gl.glShadeModel(GL2.GL_SMOOTH);
for better understending, there is a picture
after this code everything is dark and there is no light.
thank you so much for your time. :)
Related
I am relatively new to OpenGL, so this question might seem a bit trivial. I have this code in my Main.java, which is supposed to output a rectangle with the texture of the image on it:
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
int VBO = glGenBuffers(), VAO = glGenVertexArrays(), EBO = glGenBuffers();
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, false, 8, 0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, false, 8, 2);
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, false, 8, 5);
glEnableVertexAttribArray(2);
Texture texture = null;
try {
log.info("Loading texture");
texture = Texture.loadTexture("texture.png");
} catch (IOException e) {
log.severe("Texture loading failed due to IOException: " + e.getMessage());
e.printStackTrace();
}
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
if(mainProgram != null) {
mainProgram.use();
}
glBindTexture(GL_TEXTURE_2D, texture.getId());
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//...
}
My shaders are the following:
Vertex Shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;
out vec3 vertexColor;
out vec2 texCoord;
void main()
{
gl_Position = vec4(aPos , 1.0);
vertexColor = aColor;
texCoord = aTexCoord;
}
Fragment Shader:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
// texture sampler
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
The Texture class referenced above is the following:
public class Texture {
public static Texture loadTexture(String fileName) throws IOException{
//load png file
PNGDecoder decoder = new PNGDecoder(new java.io.FileInputStream(new File("C:/Users/Using/Absolute/Paths/For/Demonstration/texture.png")));
//create a byte buffer big enough to store RGBA values
ByteBuffer buffer = BufferUtils.createByteBuffer(4 * decoder.getWidth() * decoder.getHeight());
//decode
decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
//flip the buffer so its ready to read
buffer.flip();
//create a texture
int id = glGenTextures();
//bind the texture
glBindTexture(GL_TEXTURE_2D, id);
//tell opengl how to unpack bytes
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//set the texture parameters, can be GL_LINEAR or GL_NEAREST
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//upload texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Generate Mip Map
glGenerateMipmap(GL_TEXTURE_2D);
return new Texture(id);
}
private int id;
public Texture(int id){
this.id = id;
}
public int getId(){
return id;
}
}
Note that the path of the texture image is not the problem, as the code works without any Exceptions or Compiler errors. The PNGDecoder i used can be found here.
The stride and offset argument must be set in bytes when specifying the array of generic vertex attribute data by glVertexAttribPointer.
Furthermore, the uv coordinates are the 7th and 8th element in the attribute tuple:
glVertexAttribPointer(0, 3, GL_FLOAT, false, 8, 0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 8*4, 0);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 8, 2);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 8*4, 3*4);
glVertexAttribPointer(2, 2, GL_FLOAT, false, 8, 5);
glVertexAttribPointer(2, 2, GL_FLOAT, false, 8*4, 6*4);
I have an issue in my project where I am trying to draw a pyramid on screen but the depth is not being displayed.
public void create(float[] vertices, int[] indices, int numberOfVertices, int numberOfIndices) {
indexCount = numberOfIndices;
vao = gl.genVertexArrays();
gl.bindVertexArray(vao);
IntBuffer indicesBuffer = factory.create(indices);
ibo = gl.genBuffers();
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
FloatBuffer verticesBuffer = factory.create(vertices);
vbo = gl.genBuffers();
gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
gl.bufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
gl.vertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0);
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
gl.bindVertexArray(0);
}
I create my mesh object with following code where Vertices and Indices are defined as :
private void createTriangles() {
float[] vertices = new float[] {
//x y z
-1.0f, -1.0f, 0.0f, //0
0.0f, 0.0f, 1.0f, //1
1.0f, -1.0f, 0.0f, //2
0.0f, 1.0f, 0.0f //3
};
int[] indices = new int[] {
0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 1, 2
};
mesh.create(vertices, indices, 12, 12);
}
In order to display them to screen I call my render function from my game loop which is defined as.
public void render() {
gl.bindVertexArray(vao);
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
gl.drawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
gl.bindVertexArray(0);
}
To create my FloatBuffer and IntBuffer I have a factory class defined as.
public class BufferFactory {
public IntBuffer create(int[] indices) {
IntBuffer buffer = BufferUtils.createIntBuffer(indices.length);
buffer.put(indices);
buffer.flip();
return buffer;
}
public FloatBuffer create(float[] vertices) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(vertices.length);
buffer.put(vertices);
buffer.flip();
return buffer;
}
}
So the issue i'm getting is that it should have drawn four triangles to screen to form a pyramid, however my output looks like this.
I have rotated the image to try and see the depth but it is a flat object.
I have tried to identify where the issue may be coming from by attempting to draw each triangle individually by changing my render method to gl.drawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); So that it only draws one triangle. I have tried to draw all four faces individually and all are drawn to screen.
I found the issue. I was originally scaling the triangle such that
model.scale(new Vector3f(0.2f, 0.2f, 0.0f));
As a result the z axis was being multiplied by 0. Silly mistake, hope this helps someone in the future.
I have a problem regarding glBufferData and glVertexAttribPointer. For some reason, they just don't work together. Here is the code:
float[] triangleArray = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
IntBuffer vacantNameBuffer = IntBuffer.allocate(2);
gl.glGenBuffers(1, vacantNameBuffer);
int bufferIndex = vacantNameBuffer.get();
FloatBuffer triangleVertexBuffer = Buffers.newDirectFloatBuffer(triangleArray);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, bufferIndex);
IntBuffer paramBuffer = IntBuffer.allocate(2);
gl.glGetBufferParameteriv(GL2.GL_ARRAY_BUFFER, GL2.GL_BUFFER_SIZE, paramBuffer);
System.out.println(paramBuffer.get());
int triangleBufferSize = triangleVertexBuffer.capacity() * Buffers.SIZEOF_FLOAT;
gl.glBufferData(
GL2.GL_ARRAY_BUFFER,
triangleBufferSize,
triangleVertexBuffer,
GL2.GL_STATIC_DRAW);
gl.glGetBufferParameteriv(GL2.GL_ARRAY_BUFFER, GL2.GL_BUFFER_SIZE, paramBuffer);
System.out.println(paramBuffer.get());
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(
0,
3,
GL2.GL_FLOAT,
false,
0,
0);
gl.glDrawArrays(GL2.GL_TRIANGLES, 0, 3);
gl.glDisableVertexAttribArray(0);
However, this works perfectly:
float[] triangleArray = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
FloatBuffer triangleVertexBuffer = Buffers.newDirectFloatBuffer(triangleArray);
/*
IntBuffer vacantNameBuffer = IntBuffer.allocate(2);
gl.glGenBuffers(1, vacantNameBuffer);
int bufferIndex = vacantNameBuffer.get();
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, bufferIndex);
IntBuffer paramBuffer = IntBuffer.allocate(2);
gl.glGetBufferParameteriv(GL2.GL_ARRAY_BUFFER, GL2.GL_BUFFER_SIZE, paramBuffer);
System.out.println(paramBuffer.get());
int triangleBufferSize = triangleVertexBuffer.capacity() * Buffers.SIZEOF_FLOAT;
gl.glBufferData(
GL2.GL_ARRAY_BUFFER,
triangleBufferSize,
triangleVertexBuffer,
GL2.GL_STATIC_DRAW);
gl.glGetBufferParameteriv(GL2.GL_ARRAY_BUFFER, GL2.GL_BUFFER_SIZE, paramBuffer);
System.out.println(paramBuffer.get());
*/
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(
0,
3,
GL2.GL_FLOAT,
false,
0,
triangleVertexBuffer);
gl.glDrawArrays(GL2.GL_TRIANGLES, 0, 3);
gl.glDisableVertexAttribArray(0);
If someone would be so kind as to point out why my code doesn't work. I would be very grateful.
I found the problem, it was not with my code, but it's with the limitation on jogl that requires a gl shader program to be used.
Found answer on this post: glDrawArrays() behaving weirdly on Mac OS X;
So this should make a stippled triangle but all i get is normal lines. Any ideas why this issue may be caused?
private void render(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glViewport(0, 0 , 1000, 1000);
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
short stipple = (short)0xAAAA;
((GL2) gl).glLineStipple( 1, stipple );
gl.glEnable(GL_LINE_STIPPLE);
gl.glBegin(GL.GL_LINE_STRIP);
gl.glVertex3f(0f, 0.75f, 0);
gl.glVertex3f(0.5f, -0.25f, 0);
gl.glVertex3f(-0.5f, -0.25f, 0);
gl.glVertex3f(0f, 0.75f, 0);
gl.glEnd();
gl.glDisable(GL_LINE_STIPPLE);}
So far, I used the deprecated immediate mode rendering, and I'm trying to switch to VAO then VBO. 2D quads are normally rendered using VAO, but when I'm trying to attach a texture, it remains black. I would really appreciate if somebody could take a look at my code, and point out the part where I'm wrong.
public class CSpriteVAO {
/*VAO*/
private FloatBuffer vertices;
private ShortBuffer indices;
private FloatBuffer textures;
private int VAOVertices;
private int VAOIndices;
private int VAOTextures;
/*SPRITE*/
private String mTexture;
private CPoint mPosition;
private CPoint mDimension;
private CPreferences mPreferences;
public CSpriteVAO(GL2 gl, CPreferences preferences, String spriteID, CRectangle dimensions){
mPreferences = preferences;
mTexture = spriteID;
mDimension = new CPoint(dimensions.width, dimensions.height);
mPosition = new CPoint(dimensions.x, dimensions.y);
CCreateVAO(gl);
}
public void onDraw(GL2 gl){
gl.glLoadIdentity();
CBindTexture(gl);
CDraw(gl);
}
private void CDraw(GL2 gl){
//gl.glCullFace(GL2.GL_CW);
gl.glTranslatef(mPosition.x, mPosition.y, 0);
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, VAOVertices);
gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, VAOTextures);
gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, VAOTextures);
gl.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, VAOIndices);
gl.glDrawElements(GL2.GL_TRIANGLES, indices.capacity(), GL2.GL_UNSIGNED_SHORT, 0);
gl.glDisableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
}
private void CCreateVAO(GL2 gl){
//float[] textureArray = {0f, 1f, 1f, 1f, 1f, 0f, 0f, 0f};
float[] textureArray = {0f, 0f, 1f, 0f, 1f, 1f, 0f, 1f};
textures = Buffers.newDirectFloatBuffer(textureArray.length);
textures.put(textureArray);
textures.flip();
float[] vertexArray = {0, mDimension.y, 0,
mDimension.x, mDimension.y, 0,
mDimension.x, 0, 0,
0, 0, 0};
vertices = Buffers.newDirectFloatBuffer(vertexArray.length);
vertices.put(vertexArray);
vertices.flip();
short[] indexArray = {0, 1, 2, 0, 2, 3};
indices = Buffers.newDirectShortBuffer(indexArray.length);
indices.put(indexArray);
indices.flip();
int[] temp = new int[3];
gl.glGenBuffers(3, temp, 0);
VAOTextures = temp[0];
gl.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, VAOTextures);
gl.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, textures.capacity() * Buffers.SIZEOF_FLOAT, textures, GL2.GL_STATIC_DRAW);
gl.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0);
VAOVertices = temp[1];
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, VAOVertices);
gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertices.capacity() * Buffers.SIZEOF_FLOAT, vertices, GL2.GL_STATIC_DRAW);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
VAOIndices = temp[2];
gl.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, VAOIndices);
gl.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, indices.capacity() * Buffers.SIZEOF_SHORT, indices, GL2.GL_STATIC_DRAW);
gl.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0);
}
protected void CBindTexture(GL2 gl){
if (mTexture != CUtils.CurrentTexture){
if (mTexture != null){
CAssets.CWGGetTexture(mTexture).enable(gl);
CAssets.CWGGetTexture(mTexture).bind(gl);
}
CUtils.CurrentTexture = mTexture;
}
}
}
For the record: my vcard reports to have OpenGl 4.3.0 with (obviously) VAO support. Immediate rendering with textures is working fine.
I would really appreciate any kind of help. Many thanks in advance.
Check your texture coordinates.
If that does not work, check that you have set vertex color to white (so it will display colors as they show in the texture).