So we're developing a simple game in Java using LWJGL with GLFW and OpenGL 3.3.
On AMD and Intel it works perfectly but on Nvidia it doesn't. The screen is just black (the value from glClearColor), there are neither Java-exceptions nor OpenGL-Errors.
What are we doing wrong?
Main.java:
public class Main {
Shader defaultShader;
boolean running = false;
long window;
int width = 1000;
int height = 1000;
String title = "pain";
int vao;
public static void main(String[] args){
var pain = new Pain();
pain.init();
pain.run();
}
public void init() throws RuntimeException {
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) throw new RuntimeException("glfw.init.failed");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
this.window = glfwCreateWindow(this.width, this.height, this.title, 0, 0);
if (window == NULL) throw new RuntimeException("glfw.window.failed");
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
GL.createCapabilities();
glEnable(GL_TEXTURE_2D);
this.vao = glGenVertexArrays();
glBindVertexArray(vao);
this.defaultShader = new Shader("main");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
public void run() {
this.running = true;
glfwShowWindow(window);
IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer height = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);
ByteBuffer data = null;
try {
data = stbi_load_from_memory(BufferCreator.createByteBuffer(FileHandler.readFileAsBytes("fuckoff/" + "heal_powerup.png")), width, height, comp, 4);
} catch (IOException ignored) {}
if (data == null) throw new RuntimeException("texture.load.failed");
int id = glGenTextures();
int twidth = width.get();
int theight = height.get();
glBindTexture(GL_TEXTURE_2D, id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
int vid;
int tid;
int dc;
int arg4;
int[] indices = {0, 1, 2, 2, 3, 0};
dc = indices.length;
vid = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vid);
glBufferData(GL_ARRAY_BUFFER, BufferCreator.createFloatBuffer(new float[]{
0.0f, 0.0f,
100.0f, 0.0f,
100.0f, 100.0f,
0.0f, 100.0f
}), GL_DYNAMIC_DRAW);
arg4 = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arg4);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferCreator.createIntBuffer(indices), GL_STATIC_DRAW);
tid = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, tid);
glBufferData(GL_ARRAY_BUFFER, BufferCreator.createFloatBuffer(new float[]{
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
}), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
while(this.running) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
defaultShader.bind();
glBindTexture(GL_TEXTURE_2D, id);
this.defaultShader.setUniform("sampler", 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vid);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, tid);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arg4);
glDrawElements(GL_TRIANGLES, dc, GL_UNSIGNED_INT, 0);
//Unbind buffers
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Disable
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
if (glfwWindowShouldClose(window)) shutdown();
System.out.println(glGetError());
}
glfwFreeCallbacks(this.window);
glfwDestroyWindow(this.window);
glfwTerminate();
glfwSetErrorCallback(null).free();
}
void shutdown(){
this.running = false;
}
}
Shader.java:
public class Shader {
private int program, vs, fs;
public Shader(String name) {
try {
this.program = glCreateProgram();
this.vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this.vs, FileHandler.readFile("shaders/" + name + ".vs"));
glCompileShader(this.vs);
if (glGetShaderi(this.vs, GL_COMPILE_STATUS) != 1) throw new RuntimeException("shader.compile.failed\n" + glGetShaderInfoLog(vs));
this.fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this.fs, FileHandler.readFile("shaders/" + name + ".fs"));
glCompileShader(this.fs);
if (glGetShaderi(this.fs, GL_COMPILE_STATUS) != 1) throw new RuntimeException("shader.compile.failed" + glGetShaderInfoLog(fs));
glAttachShader(this.program, this.vs);
glAttachShader(this.program, this.fs);
glBindAttribLocation(this.program, 0, "vertices");
glBindAttribLocation(this.program, 1, "textures");
glLinkProgram(this.program);
if (glGetProgrami(this.program, GL_LINK_STATUS) != 1) throw new RuntimeException("shader.link.failed");
glValidateProgram(this.program);
if (glGetProgrami(this.program, GL_VALIDATE_STATUS) != 1) throw new RuntimeException("shader.validation.failed");
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public void updateShaderParameters() {
this.setUniform("sampler", 0);
int location = glGetUniformLocation(this.program, "windowSize");
if (location != 1) {
glUniform2f(location, 1000, 1000);
}
}
public void setUniform(String name, int value) {
int location = glGetUniformLocation(this.program, name);
if (location != -1) {
glUniform1i(location, value);
}
}
public void bind() {
glUseProgram(this.program);
this.updateShaderParameters();
}
}
Vertex Shader:
#version 330 core
layout (location = 0) in vec2 vertices;
layout (location = 1) in vec2 textures;
uniform vec2 windowSize;
out vec2 tex_coords;
void main() {
tex_coords = textures;
gl_Position = vec4(2.0/windowSize.x * vertices.x - 1.0, (2.0/windowSize.y * vertices.y - 1.0) * -1.0, 1, 1);
}
Fragment Shader:
#version 330 core
uniform sampler2D sampler;
out vec4 FragColor;
in vec2 tex_coords;
void main() {
if (texture(sampler, tex_coords).a != 1.0f) {
discard;
}
FragColor = texture(sampler, tex_coords);
}
BufferCreator.java and FileHandler.java are simple utility-classes which seem to work perfectly.
I assume, it has something to do with the Sampler because when I remove the if...discard statement in the Fragment Shader and set FragColor to some random values, it is drawn.
In your updateShaderParameters() method your checking for !=1 it should be !=-1 since windowSize location would be 1. If your checking for 1, it will never get set.
This could be an oversight or a mistype at the end. Happens to the best of us.
public void updateShaderParameters() {
this.setUniform("sampler", 0);
int location = glGetUniformLocation(this.program, "windowSize");
if (location != -1) {
glUniform2f(location, 1000, 1000);
}
}
Related
Hello I am trying to render texture on two triangles. glGetError() does not return any error. I can render colored rectangle, but texture does not work. Shaders are compiled without errors. Why this code does not work? (Image)
class MainRenderer implements GLSurfaceView.Renderer {
int vertexBuffer;
int indexBuffer;
int shaderProgram;
int texture;
#Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
GLES20.glClearColor(1, 0, 0, 1);
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
texture = textures[0];
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, BitmapFactory.decodeResource(MainActivity.MainActivityHandle.getResources(), R.drawable.pes), 0);
float vertices[] = {
1, 1,
1, 0,
0, 0,
0, 1
};
int indices[] = {
0, 1, 3,
1, 2, 3
};
String vertexShaderCode = "attribute vec2 position; vec2 texturePosition; void main(){texturePosition = position;gl_Position = vec4(position,0.0, 1.0);}";
String fragmentShaderCode = "precision mediump float;uniform sampler2D texture; vec2 texturePosition; void main(){gl_FragColor = texture2D(texture, texturePosition);}";
int vertexBuffers[] = new int[1];
GLES20.glGenBuffers(1, vertexBuffers, 0);
vertexBuffer = vertexBuffers[0];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffer);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 4 * 2 * 4, FloatBuffer.wrap(vertices), GLES20.GL_STATIC_DRAW);
int indexBuffers[] = new int[1];
GLES20.glGenBuffers(1, indexBuffers, 0);
indexBuffer = indexBuffers[0];
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, 2 * 3 * 4, IntBuffer.wrap(indices), GLES20.GL_STATIC_DRAW);
int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexShader, vertexShaderCode);
GLES20.glCompileShader(vertexShader);
int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, fragmentShaderCode);
GLES20.glCompileShader(fragmentShader);
shaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(shaderProgram, vertexShader);
GLES20.glAttachShader(shaderProgram, fragmentShader);
GLES20.glLinkProgram(shaderProgram);
}
#Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
#Override
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(shaderProgram);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffer);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
int positionAttributeHandle = GLES20.glGetAttribLocation(shaderProgram, "position");
GLES20.glEnableVertexAttribArray(positionAttributeHandle);
GLES20.glVertexAttribPointer(positionAttributeHandle, 2, GLES20.GL_FLOAT, false, 2*4, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_INT, 0);
GLES20.glDisableVertexAttribArray(positionAttributeHandle);
}
}
I can at least see that you are using (in vertex and fragment shaders) just 'vec2 texturePosition', while you should use a 'varying' for output from vertex shader to the fragment shader. Try adding 'varying' before 'vec2 ...' in shaders.
I have some troubles with opengles 2.0. Currently I trying to display 3D teapot model without success. Method GLES20.glDrawElements generate opengl error with number 1282 and nothing is displayed on screen.
My draw method code:
public void draw(float[] tfMVPMatrix) {
GLES20.glUseProgram(miProgramID);
miVertexPositionHandle = GLES20.glGetAttribLocation(miProgramID, VertexShader.Variables.VERTEX_POSITION.getName());
miVertexTexCoordsHandle = GLES20.glGetAttribLocation(miProgramID, VertexShader.Variables.VERTEX_TEXTURE_CORDS.getName());
miVertexNormalsHandle = GLES20.glGetAttribLocation(miProgramID, VertexShader.Variables.VERTEX_NORMALS.getName());
miProjectionMatrixHandle = GLES20.glGetUniformLocation(miProgramID, VertexShader.Variables.MVP_MATRIX.getName());
miColorHandle = GLES20.glGetUniformLocation(miProgramID, FragmentShader.Variables.COLOR.getName());
GLES20.glEnableVertexAttribArray(miVertexPositionHandle);
GLES20.glVertexAttribPointer(miProgramID, 3, GLES20.GL_FLOAT, false, 3 * Float.SIZE, moVertBuff);
GLES20.glEnableVertexAttribArray(miVertexTexCoordsHandle);
GLES20.glVertexAttribPointer(miProgramID, 2, GLES20.GL_FLOAT, false, 2 * Float.SIZE, moTexCoordBuff);
GLES20.glEnableVertexAttribArray(miVertexNormalsHandle);
GLES20.glVertexAttribPointer(miProgramID, 3, GLES20.GL_FLOAT, false, 3 * Float.SIZE, moNormBuff);
GLES20.glUniform4fv(miColorHandle, 1, COLOR, 0);
GLES20.glUniformMatrix4fv(miProjectionMatrixHandle, 1, false, tfMVPMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, miIndicesNumber, GLES20.GL_UNSIGNED_SHORT, moIndBuff); // opengl error 1282
GLES20.glDisableVertexAttribArray(miVertexPositionHandle);
GLES20.glDisableVertexAttribArray(miVertexTexCoordsHandle);
GLES20.glDisableVertexAttribArray(miVertexNormalsHandle);
}
Vertex shader code:
attribute vec4 vPosition;
attribute vec4 vNormal;
attribute vec2 vTexture;
varying vec2 texCoord;
varying vec4 normal;
uniform mat4 uMVPMatrix;
void main() {
gl_Position = uMVPMatrix * vPosition;
normal = vNormal;
texCoord = vTexture;
}
Fragment shader code:
precision mediump float;
varying vec4 normal;
uniform vec4 vColor;
void main() {
gl_FragColor = vColor;
}
My renderer code:
public class MyRenderer implements GLSurfaceView.Renderer {
private int GLProgramID;
private Demo3DObj oDemoTeapot;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private float fRatio;
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLProgram oProgram = new GLProgram();
GLProgramID = oProgram.build();
oDemoTeapot = new Demo3DObj(GLProgramID);
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
fRatio = (float)width/height;
Matrix.frustumM(mProjectionMatrix, 0, -fRatio, fRatio, -1, 1, 3, 7);
}
#Override
public void onDrawFrame(GL10 gl) {
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
oDemoTeapot.draw(mMVPMatrix);
}
}
I'm new in opengles world and I do not have any idea what can be wrong here. Can anybody help me solve this problem? What should I change here to display my model?
UPDATE!
Here is method, which is used to create moIndBuff:
private Buffer fillBufferI(int[] oContainer) {
ByteBuffer bb = ByteBuffer.allocateDirect(2 * oContainer.length);
bb.order(ByteOrder.LITTLE_ENDIAN);
for (int s : oContainer)
bb.putInt(s);
bb.rewind();
return bb;
}
I developed a simple JOGL rendering a Cube on the screen, followed the same procedure that would work on OpenGL ES 2 from IPhone. but this piece of code does not displaying anything when it is ran.
can someone help to take a browse and point out what is the problem?
Here is my Code
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
public class TestScene extends JFrame implements GLEventListener {
private static final float[] CUBE_POSITIONS = {
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
};
private static final short[] INDICIES = {
0, 1, 2, 0, 2, 3,//front
2, 1, 5, 6, 2, 5,//right
7, 6, 4, 6, 5, 4,//back
7, 4, 3, 3, 4, 0,//right
6, 7, 2, 7, 3, 2,//top
0, 4, 1, 1, 4, 5,//bottom
};
private GL4 gl;
private int program;
private Matrix4f projection = new Matrix4f();
private Matrix4f viewing = new Matrix4f();
private Matrix4f translation = new Matrix4f();
private int projectionIndex;
private int viewingMatrix;
private int transIndex;
private int positionIndex;
private int vbo;
private int vio;
public TestScene() throws HeadlessException {
super("Testing");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final GLCanvas canvas = new GLCanvas(new GLCapabilities(GLProfile.get(GLProfile.GL4)));
final FPSAnimator animator = new FPSAnimator(25);
animator.add(canvas);
animator.start();
canvas.addGLEventListener(this);
getContentPane().add(canvas);
setSize(800, 600);
setVisible(true);
}
#Override
public void init(final GLAutoDrawable drawable) {
gl = drawable.getGL().getGL4();
try {
//init program and shader
final int vertexShader = createShader("/Users/gang_liu/Develop/Java/ideaProject/KLM/JOGL_Studies_1/vertex.glsl", GL4.GL_VERTEX_SHADER);
final int fragmentShader = createShader("/Users/gang_liu/Develop/Java/ideaProject/KLM/JOGL_Studies_1/fragment.glsl", GL4.GL_VERTEX_SHADER);
program = gl.glCreateProgram();
gl.glAttachShader(program, vertexShader);
gl.glAttachShader(program, fragmentShader);
gl.glLinkProgram(program);
//generate vbo
final IntBuffer intBuffer = IntBuffer.allocate(1);
gl.glGenBuffers(1, intBuffer);
vbo = intBuffer.get();
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo);
gl.glBufferData(GL.GL_ARRAY_BUFFER, CUBE_POSITIONS.length * Buffers.SIZEOF_FLOAT, FloatBuffer.wrap(CUBE_POSITIONS), GL.GL_STATIC_DRAW);
intBuffer.flip();
//generate vio
gl.glGenBuffers(1, intBuffer);
vio = intBuffer.get();
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, vio);
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, INDICIES.length * Buffers.SIZEOF_SHORT, ShortBuffer.wrap(INDICIES), GL.GL_STATIC_DRAW);
//get program indexes
positionIndex = gl.glGetAttribLocation(program, "position");
projectionIndex = gl.glGetUniformLocation(program, "projection");
viewingMatrix = gl.glGetUniformLocation(program, "view");
transIndex = gl.glGetUniformLocation(program, "trans");
//init projection matrix;
final int width = getWidth();
final int height = getHeight();
projection.perspective(45.0f, (float)width/height, 1.0f, 100.0f);
viewing.lookAt(new Vector3f(0.0f, 0.0f, 10.0f), new Vector3f(0.0f, 0.0f, 0.0f), new Vector3f(0.0f, 1.0f, 0.0f));
} catch (final Exception ex){
ex.printStackTrace();
}
}
#Override
public void dispose(GLAutoDrawable drawable) {
}
#Override
public void display(final GLAutoDrawable drawable) {
gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
gl.glEnable(GL4.GL_CULL_FACE);
gl.glEnable(GL4.GL_DEPTH_TEST);
gl.glClearDepth(1.0);
gl.glClear(GL4.GL_COLOR_BUFFER_BIT | GL4.GL_DEPTH_BUFFER_BIT);
gl.glUseProgram(program);
gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vbo);
gl.glEnableVertexAttribArray(positionIndex);
gl.glVertexAttribPointer(positionIndex, 3, gl.GL_FLOAT, false, Buffers.SIZEOF_FLOAT * 3, 0);
gl.glUniformMatrix4fv(projectionIndex, 1, false, FloatBuffer.wrap(projection.get(new float[16])));
gl.glUniformMatrix4fv(viewingMatrix, 1, false, FloatBuffer.wrap(viewing.get(new float[16])));
gl.glUniformMatrix4fv(transIndex, 1, false, FloatBuffer.wrap(translation.get(new float[16])));
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, vio);
gl.glDrawElements(gl.GL_TRIANGLES, INDICIES.length, gl.GL_UNSIGNED_SHORT, 0);
gl.glUseProgram(0);
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
}
private int createShader(final String fileName, final int type) throws IOException {
final int shaderID = gl.glCreateShader(type);
final StringBuilder sb = new StringBuilder();
final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
gl.glShaderSource(shaderID, 1, new String[]{sb.toString()}, null, 0);
gl.glCompileShader(shaderID);
final IntBuffer intBuffer = IntBuffer.allocate(1);
gl.glGetShaderiv(shaderID, gl.GL_COMPILE_STATUS, intBuffer);
if (intBuffer.get() == gl.GL_FALSE) {
intBuffer.flip();
gl.glGetShaderiv(shaderID, gl.GL_INFO_LOG_LENGTH, intBuffer);
final int logLength = intBuffer.get();
final ByteBuffer byteBuffer = ByteBuffer.allocate(logLength);
gl.glGetShaderInfoLog(shaderID, logLength, null, byteBuffer);
System.out.println("Filed to compile " +
(type == GL4.GL_VERTEX_SHADER ? "vertex shader" : "fragment shader")
+ " shader :\n" + new String(byteBuffer.array()));
}
return shaderID;
}
public static void main(String[] args) {
new TestScene();
}
}
here are the shader files
vertex shader
#version 400
uniform lowp mat4 trans;
uniform lowp mat4 view;
uniform lowp mat4 projection;
in lowp vec3 position;
out lowp vec3 out_color;
void main(){
gl_Position = projection * view * trans * vec4(position, 1.0);
out_color = position;
}
fragment shader
#version 400
in lowp vec3 out_color;
out vec4 fragColor;
void main(){
fragColor = vec4(out_color, 1.0);
}
I know I should calculate uniform matrix in CPU. again, this is just good for debugging.
beside of this problem, I have another question. it seems some opengl functions related of a program like glGetAttribLocation and glGetUniformLocation has program parameter, so does that mean we do not have to call glUseProgram ahead of these function invocations? is that assumption correct? any opinion regarding on this question is welcome.
Thanks
This question already has answers here:
OpenGLException: Cannot use offsets when Array Buffer Object is disabled.. On a line after calling glEnable(GL_ARRAY_BUFFER)?
(2 answers)
Closed 8 years ago.
I have looked at a lot of posts, and cannot find what is wrong with my code.
I have bound my VBO however it doesn't work and gives me this error:
Exception in thread "main" org.lwjgl.opengl.OpenGLException: Cannot use
offsets when Array Buffer Object is disabled
at org.lwjgl.opengl.GLChecks.ensureArrayVBOenabled(GLChecks.java:77)
at org.lwjgl.opengl.GL20.glVertexAttribPointer(GL20.java:892)
at glsl.Main.main(Main.java:117)
I don't understand what is wrong here. I have looked everywhere and can't work out what is wrong with this. I have tried it with and without glEnable(GL_ARRAY_BUFFER_BINDING);
package glsl;
import java.nio.FloatBuffer;
import java.util.Scanner;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
public class Main
{
private static int initShaderProgram()
{
int shaderProgram = glCreateProgram();
int vertexShader = getShader(GL_VERTEX_SHADER, "/shader.vert");
glAttachShader(shaderProgram, vertexShader);
int fragmentShader = getShader(GL_FRAGMENT_SHADER, "/shader.frag");
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
checkError(shaderProgram, GL_LINK_STATUS, true);
glValidateProgram(shaderProgram);
checkError(shaderProgram, GL_VALIDATE_STATUS, true);
return shaderProgram;
}
private static int getShader(int shaderType, String shaderName)
{
int shader = glCreateShader(shaderType);
String shaderText = "";
Scanner scan = new Scanner(Main.class.getResourceAsStream(shaderName));
while(scan.hasNextLine())
shaderText = shaderText.concat(scan.nextLine().concat("\n"));
scan.close();
System.out.println("\n");
System.out.println(shaderName+" source: --------------------------------------------");
System.out.println("\n"+shaderText);
System.out.println("\n");
glShaderSource(shader, shaderText);
glCompileShader(shader);
checkError(shader, GL_COMPILE_STATUS, false);
return shader;
}
private static void checkError(int shader, int status, boolean isProgram)
{
if(!isProgram)
{
if(glGetShaderi(shader, status) == org.lwjgl.opengl.GL11.GL_FALSE)
{
System.err.println("Shader broken: " + glGetShaderInfoLog(shader, GL_INFO_LOG_LENGTH));
System.exit(1);
}
}else
{
if(glGetProgrami(shader, status) == org.lwjgl.opengl.GL11.GL_FALSE)
{
System.err.println("Shader broken: " + glGetProgramInfoLog(shader, GL_INFO_LOG_LENGTH));
System.exit(1);
}
}
}
public static void main(String[] args)
{
try
{
Display.setDisplayMode(new DisplayMode(800, 600));
Display.create();
}catch(org.lwjgl.LWJGLException e)
{
System.exit(1);
}
glEnable(GL_ARRAY_BUFFER_BINDING);
int shaderProgram = initShaderProgram();
String attribute_name = "coord2d";
int attribute_coord2d = glGetAttribLocation(shaderProgram, attribute_name);
int vboTriangle;
float[] triangleVerticesArray =
{
-1, -1,
0, 1f,
1, -1
};
FloatBuffer triangleVertices = (FloatBuffer) BufferUtils.createFloatBuffer(triangleVerticesArray.length).put(triangleVerticesArray).flip();
vboTriangle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboTriangle);
glBufferData(GL_ARRAY_BUFFER, triangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while(!Display.isCloseRequested())
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glEnableVertexAttribArray(attribute_coord2d);
glBindBuffer(GL_VERTEX_ARRAY, vboTriangle);
glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, false, 0, 0l);
glBindBuffer(GL_VERTEX_ARRAY, 0);
glDisableVertexAttribArray(attribute_coord2d);
glUseProgram(0);
Display.update();
Display.sync(60);
}
cleanup(shaderProgram, new int[]{vboTriangle});
}
private static void cleanup(int shaderProgram, int[] vbos)
{
for(int i = 0; i < vbos.length; i++)
glDeleteBuffers(vbos[i]);
glDeleteProgram(shaderProgram);
Display.destroy();
}
}
You need to set up the pointers with a VAO, a Vertex Array Object.
int vaoID = glGenVertexArrays();
Then you need to bind it, and set up the pointers with the VBOs, Vertex Array Objects.
glBindVertexArray(vaoID);
glEnableVertexAttribArray(indexLocation);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(indexLocation, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
Then everytime you render, bind the VAO, and issue a draw command.
glBindVertexArray(vaoID);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
Then finally, you need to dispose the VAO object.
glBindVertexArray(0);
glDeleteVertexArrays(vaoID);
Hope this helps.
So, I received this code from another post to SO. It seems to be the most complete working code for adding textures in openGl 2.0 with shaders in android. How does he know what integer to pass into textureResourceId, and how do I set-up a resource Id to the .png files I put into my project?
Here's the link to the SO post I'm reffering to:
Android OpenGL|ES 2.0 Texturing
And here's the Square Code:
public class Square{
private static final String TAG = "Square";
public float[] rotation = {0.0f,0.0f,45.0f};
public float[] scale = {100.0f,100f,100f};
public float[] position = {0.0f,0.0f,100f};
public float[] color = { 0.0f, 0.0f, 1.0f, 1.0f };
private int textureRef = -1;
private int mMVPMatrixHandle;
protected int DRAW_MODE = GLES20.GL_TRIANGLES;
protected int mProgram;
protected int mPositionHandle;
protected Vertex vertices;
protected Vertex texture;
private int mColorHandle;
private int vsTextureCoord;
private int fsTexture;
protected float[] result_matrix = new float[16];
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec3 vPosition;" +
"attribute vec2 TexCoordIn;" +
"varying vec2 TexCoordOut;" +
"void main() {" +
//the matrix must be included as a modifier of gl_Position
" gl_Position = uMVPMatrix * vec4(vPosition,1.0);" +
" TexCoordOut = TexCoordIn;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"uniform sampler2D Texture;" +
"varying lowp vec2 TexCoordOut;" +
"void main() {" +
" gl_FragColor = vColor*TexCoordOut*Texture;" +
"}";
//I am fully aware that I am not using the texture by assigning the colour, but until I can actually SEND the texture through, there would be no point.
static float squareCoords[] = { -0.5f, 0.5f, 0.0f, // top left
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f, // bottom right
0.5f, 0.5f, 0.0f }; // top right
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
public Square(int textureResourceId) {
int vertexShader = GFXUtils.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = GFXUtils.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // creates OpenGL ES program executables
textureRef = GFXUtils.textures.get(textureResourceId);
// initialize vertex byte buffer for shape coordinates
vertices = new Vertex(squareCoords, drawOrder, GFXUtils.COORDS_PER_VERTEX);
texture = new Vertex (new float[]
{
1.0f, 0.0f,
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
}, GFXUtils.COORDS_PER_TEXTURE);
DRAW_MODE = GLES20.GL_TRIANGLE_FAN;
}
private void getHandles()
{
//get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
if (mPositionHandle == -1) Log.e(TAG, "vPosition not found");
//get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
if (mColorHandle == -1) Log.e(TAG, "vColor not found");
//get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
if (mMVPMatrixHandle == -1) Log.e(TAG, "uMVPMatrix not found");
//get handle to texture coordinate variable
vsTextureCoord = GLES20.glGetAttribLocation(mProgram, "TexCoordIn");
if (vsTextureCoord == -1) Log.e(TAG, "TexCoordIn not found");
//get handle to shape's texture reference
fsTexture = GLES20.glGetUniformLocation(mProgram, "Texture");
if (fsTexture == -1) Log.e(TAG, "Texture not found");
}
private void translateRotateScale(float[] matrix, float[] perspectiveMatrix)
{
for (int i= 0; i < perspectiveMatrix.length;i++)
matrix[i] = perspectiveMatrix[i];
Matrix.translateM(matrix, 0, position[0], position[1], position[2]);
Matrix.rotateM(matrix, 0, rotation[0], 1.0f, 0.0f, 0.0f);
Matrix.rotateM(matrix, 0, rotation[1], 0.0f, 1.0f, 0.0f);
Matrix.rotateM(matrix, 0, rotation[2], 0.0f, 0.0f, 1.0f);
Matrix.scaleM(matrix, 0, scale[0], scale[1], scale[2]);
}
public void draw(float[] mvpMatrix) {
rotation[2]+=0.5;
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
GFXUtils.checkGlError("using program");
//Housekeeping
getHandles();
translateRotateScale(result_matrix, mvpMatrix);
//end housekeeping
// Set color for drawing the shape
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, result_matrix, 0);
GFXUtils.checkGlError("glUniformMatrix4fv");
// Prepare the shape coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, GFXUtils.COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
GFXUtils.vertexStride, vertices.floatBuffer);
GFXUtils.checkGlError("load vertex buffer");
GLES20.glVertexAttribPointer(vsTextureCoord, GFXUtils.COORDS_PER_TEXTURE,
GLES20.GL_FLOAT, false,
GFXUtils.textureStride, texture.floatBuffer);
GFXUtils.checkGlError("load texture buffer - " + vsTextureCoord);
// Enable a handle to the shape vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
GFXUtils.checkGlError("enable position handle");
GLES20.glEnableVertexAttribArray(vsTextureCoord);
GFXUtils.checkGlError("enable texture handle");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GFXUtils.checkGlError("activtexture");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureRef);
GFXUtils.checkGlError("bindtexture");
GLES20.glUniform1i(fsTexture, 0);
GFXUtils.checkGlError("uniformi");
//Draw the shape
GLES20.glDrawElements(DRAW_MODE, vertices.numIndeces, GLES20.GL_UNSIGNED_SHORT, vertices.indexBuffer);
GFXUtils.checkGlError("glDrawArrays with " + vertices.numVertices + " vertices");
//Disable vertex array
GLES20.glDisableVertexAttribArray(vsTextureCoord);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GFXUtils.checkGlError("glDisableVertexAttribArray for position");
}
}
My Main Activity Class:
public class MainActivity extends ActionBarActivity {
GLSurfaceView myGL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myGL=new MySurface(this);
setContentView(myGL);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}
//---------------------------------Open GL-------------------------------------------------------
class MySurface extends GLSurfaceView
{
private MyRenderer myRend;
public MySurface(Context context)
{
super(context);
myRend=new MyRenderer();
setEGLContextClientVersion(2);
setRenderer(myRend);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
}
Square mSquare;
float [] mViewMatrix=new float[16];
float [] mMVPMatrix=new float[16];
float [] mProjectionMatrix=new float[16];
private float[] mRotationMatrix=new float[16];
class MyRenderer implements GLSurfaceView.Renderer
{
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1f);
mSquare=new Square(R.drawable.brick_texture);
}
#Override
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
mSquare.draw(mMVPMatrix);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 2, 50);
}
}
}