I have been following the Android Developer Open GL tutorial and iv just trying to draw a square in my own program as am starting to rewrite my android game in Open GL as opposed to using the Canvas class. I have encountered a problem where it wont draw the square that i am trying to draw but it will color the background.
I am trying to draw the GLSquareEntity class which is extended from the GLEntity class, below is the code
GLSquareEntity Class:
public class GLSquareEntity extends GLEntity
{
public GLSquareEntity()
{
super();
cords = new float[] {
-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
CORDS_PER_VERTEX = 3;
drawOrder = new short[] { 0, 1, 2, 0 , 2, 3 };
// Initlise the class
setup();
}
}
GLEntity Class:
public class GLEntity
{
protected final String TAG = "GLENTITY";
// Shaders
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
// Open GL Variables
protected FloatBuffer vertexBuffer;
protected ShortBuffer drawListBuffer;
protected short[] drawOrder;
protected int CORDS_PER_VERTEX;
protected int vertexStride;
protected int vertexCount;
protected float[] cords;
// Just unill i can get an image to display
protected float[] color = {0.0f, 0.0f, 1.0f, 1.0f};
protected int program;
protected int positionHandle;
protected int colorHandle;
public GLEntity()
{
}
protected void setup()
{
Log.d(TAG, "GLEntity Setup");
vertexStride = CORDS_PER_VERTEX * 4;
vertexCount = cords.length / CORDS_PER_VERTEX;
// Initilise buffer for vertex cordernats
ByteBuffer vbuffer = ByteBuffer.allocateDirect(cords.length * 4);
vbuffer.order(ByteOrder.nativeOrder());
vertexBuffer = vbuffer.asFloatBuffer();
vertexBuffer.put(cords);
vertexBuffer.position(0);
// Initilise buffer for the draw list
ByteBuffer dlbuffer = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlbuffer.order(ByteOrder.nativeOrder());
drawListBuffer = dlbuffer.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
// Set up the shaders
int vertexShader = OpenGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = OpenGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
}
public void draw()
{
//Log.d(TAG, "Drawing GL Entity");
// Select shader program to use
GLES20.glUseProgram(program);
positionHandle = GLES20.glGetAttribLocation(program, "vPosition");
GLES20.glEnableVertexAttribArray(positionHandle);
// Prepar the data
GLES20.glVertexAttribPointer(positionHandle, CORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
// Prepare and set the color
colorHandle = GLES20.glGetUniformLocation(program, "vColor");
GLES20.glUniform4fv(colorHandle, 1, color, 0);
//GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(positionHandle);
}
}
The next classes are the GLSurfaceView class and the GLRenderer class
GLSurfaceView Class:
public class OpenGLSurfaceView extends GLSurfaceView
{
public OpenGLSurfaceView(Context context)
{
super(context);
// Set to OpenGL ES 2
setEGLContextClientVersion(2);
// Set the renderer for drawing
//OpenGLRenderer glRenderer = ;
setRenderer( new OpenGLRenderer() );
// Set to only rerender when function called
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}
}
OpenGLRenderer Class:
public class OpenGLRenderer implements GLSurfaceView.Renderer
{
GLPlayer player;
#Override
public void onDrawFrame(GL10 gl)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
player.draw();
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
GLES20.glViewport(0, 0, width, height);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
player = new GLPlayer();
}
public static int loadShader(int type, String shaderCode)
{
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
Any help figuring out what the problem is would be much appreciated :)
Thanks
Related
I've basically followed the guide on the android docs religiously, other than a couple variable names, and that I'm rendering in a fragment. I've been spending a bit off time commenting out lines and I managed to figure out that
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
//System.out.println(shader + " ass");
//GLES20.glShaderSource(shader, shaderCode);
//GLES20.glCompileShader(shader);
//return shader;
return 0;
}
the glCreateShader method crashes the app. It doesn't return anything, it just crashes. The type inputs are always either GLES20.GL_VERTEX_SHADER or GLES20.GL_FRAGMENT_SHADER it crashes with both.
The rest of my renderer class looks like this
public class OpenGLRenderer implements GLSurfaceView.Renderer {
private Triangle trangle;
#Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
trangle = new Triangle();
}
#Override
public void onSurfaceChanged(GL10 gl10, int i, int i1) {
}
#Override
public void onDrawFrame(GL10 gl10) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
//trangle.draw();
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
//System.out.println(shader + " ass");
//GLES20.glShaderSource(shader, shaderCode);
//GLES20.glCompileShader(shader);
//return shader;
return 0;
}
And here's my triangle class:
public class Triangle {
private FloatBuffer vertexBuffer;
private final int shaderProgram;
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
static float[] triangleCoords = {
0.0f, 0.5f, 0.0f,
-0.5f,-0.3f, 0.0f,
0.5f, -0.3f, 0.0f
};
static final int coordsInVertex = 3, vertexCount = triangleCoords.length / coordsInVertex, vertexStride = coordsInVertex * 4;
private int positionHandle, colorHandle;
float color[] = {1f, 0f, 0f, 1f};
public Triangle () {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(triangleCoords.length*4);
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put (triangleCoords);
vertexBuffer.position(0);
int vertexShader = OpenGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = OpenGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
shaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(shaderProgram, vertexShader);
GLES20.glAttachShader(shaderProgram, fragmentShader);
GLES20.glLinkProgram(shaderProgram);
}
public void draw () {
GLES20.glUseProgram(shaderProgram);
positionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, coordsInVertex, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
colorHandle = GLES20.glGetUniformLocation(shaderProgram, "vColor");
GLES20.glUniform4fv(colorHandle, 1, color, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
GLES20.glDisableVertexAttribArray(positionHandle);
}
}
Could someone shed some light?
Not found any issue or error in the aforementioned sources that you provided, and it is completely workable when connects with a GLSurfaceView.
I think the issue is on configuring GLSurfaceView where you must explicitly set the EGLContextClientVersion of OpenGL-ES context before setRenderer;
without eglContext program will not be performed any GL operations.
GLSurfaceView view = findViewById(R.id.glview);
view.setEGLContextClientVersion(2);
view.setRenderer(new OpenGLRenderer());
Sorry for my English. I'm beginner in OpenglES. I wrote this code to draw simple table for airhockey. The code was taken from book OpenglES2 for Android and i'm a bit to modified it. When i launched my app, it's crashed. Wherein do not appear an errors.
The code from ShaderHandler.java
public class ShaderHandler {
private static int program;
private static final String TAG = "TAG";
public static int loadShader(int type, String shaderCode){
final int shader = GLES20.glCreateShader(type);
if(shader == 0){
if(LoggerConfig.ON) {
Log.w(TAG, "Could not create new shader");
}
}
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
//----------------------------------------------------------------------------------------
//check compile status. This is pattern
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
if (LoggerConfig.ON) {
Log.v(TAG, "Results of compiling source: " + "\n" + shaderCode + "\n:"
+ GLES20.glGetShaderInfoLog(shader));
}
if (compileStatus[0] == 0){
//if it failed, delete the shader object
GLES20.glDeleteShader(shader);
if (LoggerConfig.ON) Log.w(TAG, "Compilation of shader failed");
}
//----------------------------------------------------------------------------------------
return shader;
}
public static int makeProgram(int vertexShader, int fragmentShader) {
program = GLES20.glCreateProgram();
if (program == 0){
if (LoggerConfig.ON){
Log.w(TAG, "Could not create a program");
}
}
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
if(LoggerConfig.ON) validateProgram(program);
GLES20.glUseProgram(program);
return program;
}
}
And the code from myRenderer.java
public class MyRenderer implements GLSurfaceView.Renderer {
private static final int POSITION_COMPONENT_COUNT = 2;
private static final int BYTES_PER_FLOAT = 4;
private FloatBuffer vertexData;
private Context context;
private ShaderHandler shaderHandler;
private static final String A_POSITION = "a_Position";
private int aPositionLocation;
private static final String U_COLOR = "u_Color";
private int uColorLocation;
private final String vertexShaderCode =
"attribute vec4 a_Position;" +
"void main() {" +
" gl_Position = a_Position;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 u_Color;" +
"void main() {" +
" gl_FragColor = u_Color;" +
"}";
float[] tableVertices = {
0f, 0f,
0f, 14f,
9f, 14f,
9f, 0f
};
float[] tableVerticesTriangles = {
//Triangle1
0f, 0f,
9f, 14f,
0f, 14f,
//Triangle2
0f, 0f,
9f, 0f,
9f, 14f,
//Line1
0f, 7f,
9f, 7f,
//Mallets
4.5f, 2f,
4.5f, 12f
};
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
vertexData = ByteBuffer
.allocateDirect(tableVerticesTriangles.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
vertexData.put(tableVertices);
int compiledVertShader = shaderHandler.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int compiledFragShader = shaderHandler.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
int program = shaderHandler.makeProgram(compiledVertShader, compiledFragShader);
aPositionLocation = GLES20.glGetAttribLocation(program, "a_Position");
uColorLocation = GLES20.glGetUniformLocation(program, "u_Color");
vertexData.position(0);
GLES20.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT,
false, 0, vertexData);
GLES20.glEnableVertexAttribArray(aPositionLocation);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
#Override
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUniform4f(uColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
GLES20.glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_LINES, 6, 2);
GLES20.glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_POINTS, 8, 1);
GLES20.glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_POINTS, 9, 1);
}
}
After that as app crashes, i see this message in logcat
A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 17311 (GLThread 891), pid 17264 (ockey.airhockey)
Please help. I've been trying to overcome this problem all day, but I just can’t figure out what to do.
I am trying to use open gl in my android app . i followed this doc https://developer.android.com/training/graphics/opengl/draw and i'm able to draw triangles and some complex animations using GlSurfaceView .
Now i want to use these inside a list but that can't be done with GLSurfaceView so i switcheed to TextureView . Here is an implementation to show how to do it in Grafika
https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/TextureViewGLActivity.java
Now when i put my code in the doAnimation() it doesn't work ..
i'm attaching some code
public class Triangle {
private static final String TAG = "Triangle";
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private int mProgram;
//for draw function
private int mPositionHandle;
private int mColorHandle;
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
// Use to access and set the view transformation
private int mMVPMatrixHandle;
private FloatBuffer vertexBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = { // in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
setUpShaders();
}
private void setUpShaders(){
int vertexShader = OpenGlUtil.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = OpenGlUtil.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
// creates OpenGL ES program executables
GLES20.glLinkProgram(mProgram);
GlUtil.checkGlError("glGenTextures");
}
public void draw(float[] mvpMatrix) {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
GlUtil.checkGlError("glUseProgram");
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GlUtil.checkGlError("glGetAttribLocation");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
GlUtil.checkGlError("glEnableVertexAttribArray");
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GlUtil.checkGlError("glVertexAttribPointer");
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
GlUtil.checkGlError("glUniform4fv");
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GlUtil.checkGlError("glUniformMatrix4fv");
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
GlUtil.checkGlError("glDrawArrays");
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GlUtil.checkGlError("glDisableVertexAttribArray");
}
}
this is the texture view class
public class TestTextureView extends TextureView {
private static final String TAG = "TestTextureView";
private Renderer mRenderer;
private static volatile boolean sReleaseInCallback = true;
public TestTextureView(Context context) {
super(context);
init(context);
}
public TestTextureView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public TestTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public TestTextureView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context){
// Start up the Renderer thread. It'll sleep until the TextureView is ready.
mRenderer = new Renderer(context);
mRenderer.start();
// Set the Renderer for drawing on the GLSurfaceView
setSurfaceTextureListener(mRenderer);
}
public void onDestroy(){
mRenderer.halt();
}
public Renderer getmRenderer() {
return mRenderer;
}
/**
* Handles GL rendering and SurfaceTexture callbacks.
* <p>
* We don't create a Looper, so the SurfaceTexture-by-way-of-TextureView callbacks
* happen on the UI thread.
*/
public static class Renderer extends Thread implements SurfaceTextureListener {
private Object mLock = new Object(); // guards mSurfaceTexture, mDone
private SurfaceTexture mSurfaceTexture;
private EglCore mEglCore;
private boolean mDone;
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private int starshipType=Config.TYPE_STARSHIP_LIFE,numMoons=1,type_phase=1;
private int level=1;
private Bitmap newProfileBitmap,newVesselBitmap;
//for life
private ArrayList<Shape> list;
private String name;
private Image image,imageStar,imageStar2,imageStar3;
private CircleImage circleImage,planet;
float degrees=0,degrees2=120,degrees3=240;
float shrinkingDegrees=0,animScale=0;
private float[] star1Array,star2Array,star3Array;
private float[] vesselArray,profileArray,planetArray;
private float baseTranslation=1;
private Context context;
public Renderer(Context context) {
this.context = context;
}
/**
* Tells the thread to stop running.
*/
public void halt() {
synchronized (mLock) {
mDone = true;
mLock.notify();
}
}
#Override // will be called on UI thread
public void onSurfaceTextureAvailable(SurfaceTexture st, int width, int height) {
Log.d(TAG, "onSurfaceTextureAvailable(" + width + "x" + height + ")");
synchronized (mLock) {
mSurfaceTexture = st;
mLock.notify();
}
}
#Override // will be called on UI thread
public void onSurfaceTextureSizeChanged(SurfaceTexture st, int width, int height) {
Log.d(TAG, "onSurfaceTextureSizeChanged(" + width + "x" + height + ")");
// TODO: ?
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
#Override // will be called on UI thread
public boolean onSurfaceTextureDestroyed(SurfaceTexture st) {
Log.d(TAG, "onSurfaceTextureDestroyed");
// We set the SurfaceTexture reference to null to tell the Renderer thread that
// it needs to stop. The renderer might be in the middle of drawing, so we want
// to return false here so that the caller doesn't try to release the ST out
// from under us.
//
// In theory.
//
// In 4.4, the buffer queue was changed to be synchronous, which means we block
// in dequeueBuffer(). If the renderer has been running flat out and is currently
// sleeping in eglSwapBuffers(), it's going to be stuck there until somebody
// tears down the SurfaceTexture. So we need to tear it down here to ensure
// that the renderer thread will break. If we don't, the thread sticks there
// forever.
//
// The only down side to releasing it here is we'll get some complaints in logcat
// when eglSwapBuffers() fails.
synchronized (mLock) {
mSurfaceTexture = null;
}
if (sReleaseInCallback) {
Log.i(TAG, "Allowing TextureView to release SurfaceTexture");
}
return sReleaseInCallback;
}
#Override // will be called on UI thread
public void onSurfaceTextureUpdated(SurfaceTexture st) {
//Log.d(TAG, "onSurfaceTextureUpdated");
}
#Override
public void run() {
while (true) {
SurfaceTexture surfaceTexture = null;
// Latch the SurfaceTexture when it becomes available. We have to wait for
// the TextureView to create it.
synchronized (mLock) {
while (!mDone && (surfaceTexture = mSurfaceTexture) == null) {
try {
mLock.wait();
} catch (InterruptedException ie) {
throw new RuntimeException(ie); // not expected
}
}
if (mDone) {
break;
}
}
Log.d(TAG, "Got surfaceTexture=" + surfaceTexture);
// Create an EGL surface for our new SurfaceTexture. We're not on the same
// thread as the SurfaceTexture, which is a concern for the *consumer*, which
// wants to call updateTexImage(). Because we're the *producer*, i.e. the
// one generating the frames, we don't need to worry about being on the same
// thread.
mEglCore = new EglCore(null, EglCore.FLAG_TRY_GLES3);
WindowSurface windowSurface = new WindowSurface(mEglCore, mSurfaceTexture);
windowSurface.makeCurrent();
//setEGLContextClientVersion();
// Render frames until we're told to stop or the SurfaceTexture is destroyed.
doAnimation(windowSurface);
windowSurface.release();
mEglCore.release();
if (!sReleaseInCallback) {
Log.i(TAG, "Releasing SurfaceTexture in renderer thread");
surfaceTexture.release();
}
}
Log.d(TAG, "Renderer thread exiting");
}
/**
* Draws updates as fast as the system will allow.
* <p>
* In 4.4, with the synchronous buffer queue queue, the frame rate will be limited.
* In previous (and future) releases, with the async queue, many of the frames we
* render may be dropped.
* <p>
* The correct thing to do here is use Choreographer to schedule frame updates off
* of vsync, but that's not nearly as much fun.
*/
private void doAnimation(WindowSurface eglSurface) {
final int BLOCK_WIDTH = 80;
final int BLOCK_SPEED = 2;
float clearColor = 0.0f;
int xpos = -BLOCK_WIDTH / 2;
int xdir = BLOCK_SPEED;
int width = eglSurface.getWidth();
int height = eglSurface.getHeight();
Log.d(TAG, "Animating " + width + "x" + height + " EGL surface");
while (true) {
// Check to see if the TextureView's SurfaceTexture is still valid.
synchronized (mLock) {
SurfaceTexture surfaceTexture = mSurfaceTexture;
if (surfaceTexture == null) {
Log.d(TAG, "doAnimation exiting");
return;
}
}
//Log.d(TAG, "doAnimation: loading new frame");
/*
//ORIGINAL CODE IN GRAFIKA ----------------------------------------------
// Still alive, render a frame.
GLES20.glClearColor(clearColor, clearColor, clearColor, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
GLES20.glScissor(xpos, height / 4, BLOCK_WIDTH, height / 2);
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
// Publish the frame. If we overrun the consumer, frames will be dropped,
// so on a sufficiently fast device the animation will run at faster than
// the display refresh rate.
//
// If the SurfaceTexture has been destroyed, this will throw an exception.
eglSurface.swapBuffers();
// Advance state
clearColor += 0.015625f;
if (clearColor > 1.0f) {
clearColor = 0.0f;
}
xpos += xdir;
if (xpos <= -BLOCK_WIDTH / 2 || xpos >= width - BLOCK_WIDTH / 2) {
Log.d(TAG, "change direction");
xdir = -xdir;
}
*/
//MY CODE -----------------------------------------
onDrawFrame();
//eglSurface.swapBuffers();
if (!eglSurface.swapBuffers()) {
Log.e(TAG, "cannot swap buffers!");
}
GlUtil.checkGlError("cannot swap buffers");
}
}
boolean created=false;
Triangle triangle;
private void setUpObjects(){
image=new Image(context, -1);
imageStar=new Image(context,R.drawable.moon1);
imageStar2=new Image(context,R.drawable.moon2);
imageStar3=new Image(context,R.drawable.moon3);
circleImage=new CircleImage(context,R.drawable.profile);
planet=new CircleImage(context,R.drawable.earth);
triangle=new Triangle();
setInitialSettings();
}
private void setInitialSettings(){
// Set the background color to black ( rgba ).
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0f);
GLES20.glClearDepthf(1.0f);
GLES20.glEnable( GLES20.GL_DEPTH_TEST );
GLES20.glDepthFunc( GLES20.GL_LEQUAL );
//https://stackoverflow.com/questions/3388294/opengl-question-about-the-usage-of-gldepthmask/3390094#3390094
GLES20.glDepthMask( true );
}
private void onDrawFrame(){
//Log.d(TAG, "onDrawFrame: ");
if(!created){
setUpObjects();
created=true;
}
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
triangle.draw(mProjectionMatrix);
}
}
}
I am new to OpenGL and I just begin to try LWJGL, everything worked fine until I added the PVM matrices, I don't know why nothing shows up when I added them.
The matrices related code is commented.
Here is the code :
public class Window {
private int vaoid;
private int vbover;
private int vboind;
private int vid;
private int fid;
private int pid;
//private int pml;projection matrix location
//private int vml;view matrix location
//private int mml;model matrix location
//private Matrix4f projectionMatrix;
//private Matrix4f viewMatrix;
//private Matrix4f modelMatrix;
//private FloatBuffer projbuffer = BufferUtils.createFloatBuffer(16);
public void start() {
try {
Display.setDisplayMode(new DisplayMode(800,600));
Display.setTitle("OpenGL Try");
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
init();
while (!Display.isCloseRequested()) {
update();
Display.sync(60);
Display.update();
}
cleanUp();
Display.destroy();
}
public static void main(String[] argv) {
Window displayExample = new Window();
displayExample.start();
}
public void init() {
//projectionMatrix = createProjectionMatrix();
float[] vertices = {
-0.5f, 0.5f, 0f, // Left top ID: 0
-0.5f, -0.5f, 0f, // Left bottom ID: 1
0.5f, -0.5f, 0f, // Right bottom ID: 2
0.5f, 0.5f, 0f // Right left ID: 3
};
FloatBuffer verticesbuffer = BufferUtils.createFloatBuffer(vertices.length);
verticesbuffer.put(vertices);
verticesbuffer.flip();
byte[] indices = {
// Left bottom triangle
0, 1, 2,
// Right top triangle
2, 3, 0
};
ByteBuffer indicesbuffer = BufferUtils.createByteBuffer(indices.length);
indicesbuffer.put(indices);
indicesbuffer.flip();
vaoid = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoid);
vbover = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbover);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER,verticesbuffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0,3,GL11.GL_FLOAT,false,0,0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,0);
GL30.glBindVertexArray(0);
vboind = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER,vboind);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER,indicesbuffer,GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER,0);
vid = loadShader("./res/shader.ver",GL20.GL_VERTEX_SHADER);
fid = loadShader("./res/shader.frag",GL20.GL_FRAGMENT_SHADER);
pid = GL20.glCreateProgram();
GL20.glAttachShader(pid,vid);
GL20.glAttachShader(pid, fid);
GL20.glBindAttribLocation(pid, 0, "in_position");
GL20.glLinkProgram(pid);
GL20.glValidateProgram(pid);
//pml = GL20.glGetUniformLocation(pid, "projMatrix");
//vml = GL20.glGetUniformLocation(pid, "viewMatrix");
//mml = GL20.glGetUniformLocation(pid, "modelMatrix");
GL20.glUseProgram(pid);
//projectionMatrix.store(projbuffer);
//projbuffer.flip();
//GL20.glUniformMatrix4(pml, false, projbuffer);
GL20.glUseProgram(0);
}
public void update() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
GL20.glUseProgram(pid);
//viewMatrix = createTransformationMatrix(new Vector3f(0,0,0),new Vector3f(0,0,0),1f);
//viewMatrix.store(projbuffer);projbuffer.flip();
//GL20.glUniformMatrix4(vml, false, projbuffer);
//modelMatrix = createTransformationMatrix(new Vector3f(0,0,0),new Vector3f(0,0,0),1f);
//modelMatrix.store(projbuffer);projbuffer.flip();
//GL20.glUniformMatrix4(mml, false, projbuffer);
GL30.glBindVertexArray(vaoid);
GL20.glEnableVertexAttribArray(0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER,vboind);
GL11.glDrawElements(GL11.GL_TRIANGLES,6,GL11.GL_UNSIGNED_BYTE,0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER,0);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
GL20.glUseProgram(0);
}
public void cleanUp() {
GL20.glUseProgram(0);
GL20.glDetachShader(pid, vid);
GL20.glDetachShader(pid, fid);
GL20.glDeleteShader(vid);
GL20.glDeleteShader(fid);
GL20.glDeleteProgram(pid);
GL20.glDisableVertexAttribArray(0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glDeleteBuffers(vbover);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL15.glDeleteBuffers(vboind);
GL30.glBindVertexArray(0);
GL30.glDeleteVertexArrays(vaoid);
}
public int loadShader(String filePath,int type) {
StringBuilder sb = new StringBuilder();
int shaderId = 0;
try {
BufferedReader br = new BufferedReader(new FileReader(filePath));
String line="";
while((line = br.readLine())!=null) {
sb.append(line).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
shaderId = GL20.glCreateShader(type);
GL20.glShaderSource(shaderId, sb);
GL20.glCompileShader(shaderId);
return shaderId;
}
/* public Matrix4f createTransformationMatrix(Vector3f pos,Vector3f
rot,float scale) {
Matrix4f mat = new Matrix4f();
Matrix4f.scale(new Vector3f(scale,scale,scale),mat,mat);
Matrix4f.translate(pos,mat,mat);
Matrix4f.rotate((float) Math.toRadians(rot.x),new
Vector3f(1,0,0),mat,mat);
Matrix4f.rotate((float) Math.toRadians(rot.y),new
Vector3f(0,1,0),mat,mat);
Matrix4f.rotate((float) Math.toRadians(rot.z),new
Vector3f(0,0,1),mat,mat);
return mat;
}*/
/*public Matrix4f createProjectionMatrix() {
Matrix4f pm = new Matrix4f();
float fieldOfView = 60f;
float aspectRatio = (float)Display.getWidth()/(float)Display.getHeight();
float znear = 0.1f;
float zfar = 100f;
float frustumLength = zfar-znear;
float ysize = (float) (1/Math.tan(Math.toRadians(fieldOfView/2f)));
float xsize = ysize/aspectRatio;
pm.m00 = xsize;
pm.m11 = ysize;
pm.m22 = -((znear+zfar)/frustumLength);
pm.m23 = -1;
pm.m32 = -((2*znear*zfar)/frustumLength);
pm.m33 = 0;
return pm;
} */
}
And the vertex shader :
#version 150 core
in vec3 in_position;
uniform mat4 projMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
out vec4 pass_color;
void main(void){
gl_Position = projMatrix * viewMarix * modelMatrix *
vec4(in_position,1.0);
pass_color = vec4(1,0,1,1);
}
And the fragment shader :
#version 150 core
in vec4 pass_color;
out vec4 out_color;
void main(void){
out_color = pass_color;
}
Any help is appreciated ,that block me to continue learning the new opengl stuff, thank you.
I've noticed 3 problems.
You should use an IntBuffer instead of a ByteBuffer for the indices, because you store integers in this buffer. If you change the buffer type you need to also change GL_UNSIGNED_BYTE in glDrawElements to GL_UNSIGNED_INT.
Don't bind GL_ELEMENT_ARRAY_BUFFER to 0 after binding the indices buffer.
You don't need to bind and unbind GL_ELEMENT_ARRAY_BUFFER when calling glDarwElements
I hope this helps.
I'm doing some beginning work with shaders in LibGDX. I'm trying to set the color manually but all I get is white.
vertex shader:
attribute vec4 a_position;
uniform mat4 u_projTrans;
void main() {
gl_Position = u_projTrans * a_position;
gl_PointSize = 10.0;
}
fragment shader:
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Extremely simple as you can see. With this setup I am able to draw shapes, but they always come out white. With my fragment shader I would expect everything to be red.
Am I missing something in the libgdx stack? Is something getting overridden further up the chain by some libgdx shader defaults or something?
Screen output:
Somehow you need to pass vertex to OpenGL so LibGDX having Mesh class for this requirement. I am using SpriteBatch that having own mesh that use to draw.
Vertex Shader :
attribute vec4 a_position;
uniform mat4 u_projTrans;
void main()
{
gl_Position = u_projTrans * a_position;
}
Fragment Shader :
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
void main()
{
gl_FragColor = vec4(1,0,0,1);
}
ShaderTest
public class ShaderTest extends ApplicationAdapter {
SpriteBatch spriteBatch;
Texture texture;
ShaderProgram shaderProgram;
#Override
public void create() {
spriteBatch=new SpriteBatch();
shaderProgram=new ShaderProgram(Gdx.files.internal("default.vertex.glsl"),Gdx.files.internal("default.fragment.glsl"));
shaderProgram.pedantic = false;
if(shaderProgram.isCompiled()) {
System.out.println("Compiled Successfully");
spriteBatch.setShader(shaderProgram);
}else {
System.out.println("Some Problem in Shader");
}
texture=new Texture("badlogic.jpg");
}
#Override
public void render() {
Gdx.gl.glClearColor(1,1,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.begin();
spriteBatch.draw(texture,100,100);
spriteBatch.end();
}
#Override
public void dispose() {
shaderProgram.dispose();
texture.dispose();
spriteBatch.dispose();
}
}
And the output is :
EDIT
Mesh is nothing, It is just a big array of vertices, contains value that required by OpenGL and a single vertex can hold information about Position, Color, Texture Coordinates, or whatever else we would like to pass to the shaders.
According to question you fixed colour in fragment shader that is RED so you only need to pass position of quard to OpenGL.
public class QuardTest extends ApplicationAdapter {
Mesh quard;
OrthographicCamera cam;
ShaderProgram shaderProgram;
private int Idx = 0;
private float[] verts= new float[4 * 2];
#Override
public void create() {
cam=new OrthographicCamera();
shaderProgram=new ShaderProgram(Gdx.files.internal("default.vertex.glsl"),Gdx.files.internal("default.fragment.glsl"));
if(shaderProgram.isCompiled()) {
System.out.println("Compiled Successfully");
}else {
System.out.println("Some Problem in Shader");
}
quard =new Mesh(true,4,0,new VertexAttribute(VertexAttributes.Usage.Position, 2, "a_position"));
}
#Override
public void render() {
Gdx.gl.glClearColor(1,1,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
drawRect(100,100,100,100);
drawRect(250,250,50,50);
}
public void drawRect(float x, float y, float width, float height){
if (Idx ==verts.length) {
flush();
}
verts[Idx++] = x;
verts[Idx++] = y;
verts[Idx++] = x + width;
verts[Idx++] = y;
verts[Idx++] = x + width;
verts[Idx++] = y + height;
verts[Idx++] = x;
verts[Idx++] = y + height;
}
public void flush(){
if (Idx ==0)
return;
quard.setVertices(verts);
Gdx.gl.glDepthMask(false);
int vertexCount = (Idx /2);
cam.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
shaderProgram.begin();
shaderProgram.setUniformMatrix("u_projTrans", cam.combined);
quard.render(shaderProgram, GL20.GL_TRIANGLE_FAN, 0, vertexCount);
shaderProgram.end();
Gdx.gl.glDepthMask(true);
Idx =0;
}
}