OpenGL ES 1.0 strange texture behavior - java

I am learning how to work with OpenGL ES 1.0 (I was told that it is better to start with "1.0"/"1.1").
I am trying to create transperent 3D globe on android device using transparent texture and vertex indexing but having problem which I don't understand and can't find any solution on internet.
The problem is that depending on angle of camera rotation my globe stops rendering "back side" of sphere or sphere back sides texture. On image below you can see what happens if I rotate camera in same direction.
Link to image: CLICK HERE (I have no reputation to add image directly, sorry)
So can you help me? What is my mistake, why "back" is disappearing?
"Sphere" class:
package com.example.OpenGL_Testing.openGl.geometry;
import com.example.OpenGL_Testing.openGl.Texture;
import javax.microedition.khronos.opengles.GL10;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class Sphere {
float step = 5f; // density of sphere; step in degrees
float[] verArray;
float[] texIndex;
short[] verIndex;
private FloatBuffer vBuff;
private FloatBuffer tBuff;
private ShortBuffer iBuff;
public final float mCenterX, mCenterY, mCenterZ;
public final float mRadius;
private final GL10 mGL;
private int stepsPai, stepsTheta;
private Texture texture;
public Sphere(float mRadius, float mCenterX, float mCenterY, float mCenterZ, GL10 mGL) {
this.mGL = mGL;
// sphere parameters
this.mRadius = mRadius;
this.mCenterX = mCenterX;
this.mCenterY = mCenterY;
this.mCenterZ = mCenterZ;
stepsPai = (int) (180f / step) ; //sphere vertical 'lines'
stepsTheta = (int) (360f / step) + 1; //sphere horizontal 'lines'
// create sphere 'dots'
createVerticesBuff();
createIndexingBuffer();
}
private float[] createVerticesArray() {
float[] vertices = new float[stepsPai * stepsTheta * 3];
int n = 0;
float cRadius, cHeight, co, si;
for (float pai = 180f - step; pai > 0f; pai -= step) {
cRadius = (float) Math.sin((pai + step) * Math.PI / 180f);
cHeight = (float) Math.cos((pai + step) * Math.PI / 180f);
for (float theta = 0.0f; theta <= 360f; theta += step) {
co = (float) Math.cos(theta * Math.PI / 180f);
si = -(float) Math.sin(theta * Math.PI / 180f);
vertices[n * 3] = mRadius * (cRadius * co) + mCenterX;
vertices[n * 3 + 1] = mRadius * (cHeight) + mCenterY;
vertices[n * 3 + 2] = mRadius * (cRadius * si) + mCenterZ;
n ++;
}
}
return vertices;
}
public FloatBuffer createVerticesBuff() {
// create array
verArray = createVerticesArray();
// create buffer
if (vBuff == null) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(verArray.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vBuff = byteBuffer.asFloatBuffer();
vBuff.put(verArray);
vBuff.flip();
}
return vBuff;
}
public short[] createIndexingArray() {
short[] indexies = new short[verArray.length*2];
int n=0;
for (int i = 0; i < stepsPai-1; i++) {
for (int j = 0; j < stepsTheta; j++) {
indexies[n] = (short) (i*stepsTheta+j);
indexies[n+1] = (short) ((i+1)*stepsTheta+j);
indexies[n+2] = (short) ((i+1)*stepsTheta+j+1);
indexies[n+3] = indexies[n+2];
indexies[n+4] = (short) (i*stepsTheta+j+1);
indexies[n+5] = indexies[n];
n+=6;
}
}
return indexies;
}
public void createIndexingBuffer(){
// create array
verIndex = createIndexingArray();
//create buffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(verIndex.length * 2);
byteBuffer.order(ByteOrder.nativeOrder());
iBuff = byteBuffer.asShortBuffer();
iBuff.put(verIndex);
iBuff.flip();
}
public void draw() {
// setup vertices buffer
mGL.glEnableClientState(GL10.GL_VERTEX_ARRAY);
vBuff.position(0);
mGL.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuff);
// setup texture
if (texture != null) {
mGL.glEnable(GL10.GL_TEXTURE_2D);
mGL.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
tBuff.position(0);
mGL.glTexCoordPointer(2, GL10.GL_FLOAT, 0, tBuff);
}
// display poligons on screen
mGL.glDrawElements(GL10.GL_TRIANGLES, verIndex.length, GL10.GL_UNSIGNED_SHORT, iBuff);
// reset settings
if (texture != null) {
mGL.glDisable(GL10.GL_TEXTURE_2D);
mGL.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
} else {
mGL.glColor4f(1, 1, 1, 1);
}
mGL.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
public void setTexture(Texture texture) {
if (this.texture != null) {
this.texture.dispose();
}
this.texture = texture;
// create array
texIndex = new float[stepsPai * stepsTheta * 2 * 2];
int n = 0;
for (float pai = 0f; pai < 180f; pai += step) {
for (float theta = 0.0f; theta <= 360f; theta += step) {
texIndex[n] = theta / 360f;
texIndex[n + 1] = pai / 180f;
n += 2;
}
}
// create buffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(texIndex.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
tBuff = byteBuffer.asFloatBuffer();
tBuff.put(texIndex);
tBuff.flip();
// bind texture
texture.bind();
}
}
"World" class
package com.example.OpenGL_Testing.openGl;
import android.opengl.GLSurfaceView;
import android.support.v4.view.GestureDetectorCompat;
import android.view.MotionEvent;
import android.view.View;
import com.example.OpenGL_Testing.MyApp;
import com.example.OpenGL_Testing.MyGestureListener;
import com.example.OpenGL_Testing.Screen;
import com.example.OpenGL_Testing.openGl.geometry.Sphere;
import com.example.OpenGL_Testing.openGl.geometry.Sphere2;
import javax.microedition.khronos.opengles.GL10;
/**
* Created by Aleksandr.Tsatski on 11.11.2014.
*/
public class WorldMap implements Screen {
GLSurfaceView glView;
static final int VERTEX_SIZE = (3) * 4;
Sphere sphere;
GL10 gl;
private GestureDetectorCompat mDetector;
final Object stateChanged = new Object();
public WorldMap(final GLSurfaceView glView, final GL10 gl) {
this.glView = glView;
this.gl = gl;
sphere = new Sphere(400, 0, 0, 0, gl);
}
private void setupGestureListener(final GLSurfaceView glView, final GL10 gl) {
final MyGestureListener listener = new MyGestureListener();
listener.setGestureFeedBackListener(new MyGestureListener.Feedback() {
#Override
public void onFeedback(final int event, final float parameter1, final float parameter2) {
glView.queueEvent(new Runnable() {
#Override
public void run() {
switch (event) {
case MyGestureListener.SCROLL:
gl.glRotatef(parameter1/10, 0f, 1f, 0f);
gl.glRotatef(-parameter2/10, 0f, 0f, 1f);
break;
default:
break;
}
}
});
}
});
glView.post(new Runnable() {
#Override
public void run() {
mDetector = new GestureDetectorCompat(MyApp.getAppContext(), listener);
}
});
glView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return mDetector.onTouchEvent(motionEvent);
}
});
}
#Override
public void present(float deltaTime) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
sphere.draw();
}
#Override
public void resume() {
gl.glClearColor(1, 0, 0, 1);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
setupGestureListener(glView, gl);
sphere.setTexture(new Texture(gl, "world_map.png"));
}
#Override
public void pause() {
}
#Override
public void dispose() {
}
}

Related

Libgdx - Rotate an object using its movement

I'm trying to implement an autorotation method for a SpriteAnimation class (trying to port SpriteAnimation).
Everything is working, the sprite draws correctly (it uses the correct animations) it just doesn't rotate properly if at all, normally it seems to point to the origin (0, 0) only after its target matches its position while I want its rotation to update as it moves, i've tried both degrees and radians, neither of which work. It should be rotating to match the current direction it's going. I've been struggling with this for about a week now, but still have not gotten the desired result.
Full Code Here
Relevant code:
From SpriteAnimation
// The x position of the sprite's upper left corner pixel.
public int getX() { return (int)position.x; }
public void setX(int value)
{
prevPosition.x = position.x;
position.x = value;
updateRotation();
}
// The y position of the sprite's upper left corner pixel.
public int getY() { return (int)position.y; }
public void setY(int value)
{
prevPosition.y = position.y;
position.y = value;
updateRotation();
}
void updateRotation()
{
if (rotateByPosition)
{
Vector2 rotationVector = new Vector2(position.x - prevPosition.x, position.y - prevPosition.y);
rotationRad = rotationVector.angle();
rotationDeg = rotationRad * MathUtils.radiansToDegrees;
}
}
public void MoveBy(int x, int y)
{
prevPosition = new Vector2(position);
position.x += x;
position.y += y;
updateRotation();
}
public void Update(float deltaTime)
{
// Don't do anything if the sprite is not animating
if (animating)
{
// If there is not a currently active animation
if (getCurrentFrameAnimation() == null)
{
// Make sure we have an animation associated with this sprite
if (animations.size() > 0)
{
// Set the active animation to the first animation
// associated with this sprite
String[] sKeys = new String[animations.size()];
int index = 0;
for (Entry<String, FrameAnimation> mapEntry : animations.entrySet()) {
sKeys[index] = mapEntry.getKey();
index++;
}
setCurrentAnimation(sKeys[0]);
}
else
{
return;
}
}
// Run the Animation's update method
getCurrentFrameAnimation().Update(deltaTime);
// Check to see if there is a "follow-up" animation named for this animation
if (getCurrentFrameAnimation().getNextAnimation() != null && !getCurrentFrameAnimation().getNextAnimation().isEmpty())
{
// If there is, see if the currently playing animation has
// completed a full animation loop
if (getCurrentFrameAnimation().getPlayCount() > 0)
{
// If it has, set up the next animation
setCurrentAnimation(getCurrentFrameAnimation().getNextAnimation());
}
}
}
}
public void Draw(SpriteBatch spriteBatch, int xOffset, int yOffset)
{
updateRotation(); // Calling this while testing to make sure that it is being called
spriteBatch.draw(getCurrentTextureRegion(), getPosition().x + xOffset - center.x, getPosition().y + yOffset - center.y, center.x, center.y, getCurrentFrameAnimation().getFrameWidth(), getCurrentFrameAnimation().getFrameHeight(), 1.0f, 1.0f, rotationRad);
}
TestScreen class
package com.darkstudio.darkisle.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.darkstudio.darkisle.DarkIsle;
import com.delib.engine.sprite.MobileSprite;
/**
* Created by DarkEnder on 2017/06/27.
*/
public class TestScreen implements Screen {
final DarkIsle game;
OrthographicCamera camera;
Texture tankTexture;
MobileSprite mouseTank;
public TestScreen(final DarkIsle game)
{
this.game = game;
camera = new OrthographicCamera();
configureCamera();
tankTexture = new Texture(Gdx.files.internal("MulticolorTanks.png"));
mouseTank = new MobileSprite(tankTexture, 32, 32);
mouseTank.getSprite().AddAnimation("red", 0, 32, 32, 32, 8, 0.1f);
mouseTank.getSprite().AddAnimation("purple", 0, 128, 32, 32, 8, 0.1f, "red");
mouseTank.getSprite().AddAnimation("yellow", 0, 64, 32, 32, 8, 0.1f);
mouseTank.getSprite().setAutoRotate(true);
mouseTank.setPosition(new Vector2(100, 100));
mouseTank.setTarget(new Vector2(mouseTank.getPosition()));
mouseTank.setIsPathing(true);
mouseTank.setEndPathAnimation("yellow");
mouseTank.setLoopPath(false);
mouseTank.setSpeed(2);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
update();
game.batch.begin();
mouseTank.draw(game.batch);
game.batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
private void configureCamera()
{
Vector3 camPos = new Vector3(camera.position);
float size = 800;
float cameraWidth = 0;
float cameraHeight = 0;
if (Gdx.graphics.getHeight() < Gdx.graphics.getWidth())
{
cameraWidth = size;
cameraHeight = size * Gdx.graphics.getHeight() / Gdx.graphics.getWidth();
}
else
{
cameraWidth = size * Gdx.graphics.getWidth() / Gdx.graphics.getHeight();
cameraHeight = size;
}
camera.setToOrtho(true, cameraWidth, cameraHeight);
camera.position.set(camPos.x + camera.viewportWidth / 2f, camPos.y + camera.viewportHeight / 2f, 0);
}
private void update() {
int xTouch = Gdx.input.getX(0);
int yTouch = Gdx.input.getY(0);
mouseTank.setTarget(xTouch, yTouch);
mouseTank.update(Gdx.graphics.getDeltaTime());
}
}
Edit: Just saying now that I've already tried using atan2 in MathUtils and it gave the same results.
The MobileSprite update method
public void update(float deltaTime)
{
if (active && movingTowardsTarget)
{
if ((target != null))
{
// Get a vector pointing from the current location of the sprite
// to the destination.
Vector2 Delta = new Vector2(target.x - sprite.getX(), target.y - sprite.getY());
if (Delta.len() > getSpeed())
{
Delta.nor();
Delta.scl(getSpeed());
getPosition().add(Delta);
}
else
{
if (target == sprite.getPosition())
{
if (pathing)
{
if (queuePath.size() > 0)
{
target = queuePath.remove();
if (loopPath)
{
queuePath.remove(target);
}
}
else
{
if (!(endPathAnimation == null))
{
if (!(getSprite().getCurrentAnimation() == endPathAnimation))
{
getSprite().setCurrentAnimation(endPathAnimation);
}
}
if (deactivateAtEndOfPath)
{
setIsActive(false);
}
if (hideAtEndOfPath)
{
setIsVisible(false);
}
}
}
}
else
{
sprite.setPosition(target);
}
}
}
}
if (active)
sprite.Update(deltaTime);
}
To get the radians angle:
void updateRotation()
{
if (rotateByPosition)
{
Vector2 rotationVector = new Vector2(position.x - prevPosition.x, position.y - prevPosition.y);
rotationRad = rotationVector.angleRad();
rotationDeg = rotationRad * MathUtils.radiansToDegrees;
}
}
and the draw method needs a degrees angle:
spriteBatch.draw(
getCurrentTextureRegion(),
getPosition().x + xOffset - center.x,
getPosition().y + yOffset - center.y,
center.x, center.y,
getCurrentFrameAnimation().getFrameWidth(), getCurrentFrameAnimation().getFrameHeight(),
1.0f, 1.0f,
rotationDeg
);
The screen mouse position is from the upper left corner the renderer needs from the bottom left corner:
int xTouch = Gdx.input.getX(0);
int yTouch = Gdx.graphics.getHeight() - Gdx.input.getY(0);

rendering 3d lwjgl flat terrain doesn't work

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.opengl.GL15.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWCursorPosCallback;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;
import org.omg.Messaging.SYNC_WITH_TRANSPORT;
public class man {
private static final int VERTEX_COUNT = 128;
private static final float SIZE = 1;
public static int count;
public static int vid;
public static int iid;
public static int program;
public static float fov = 70f;
public static float near = 0.1f;
public static float far = 1000f;
public static Matrix4f modelMatrix = new Matrix4f() ;
public static Matrix4f view = new Matrix4f();
public static Matrix4f projectionmatrix = new Matrix4f();
public static GLFWCursorPosCallback mouseCallback;
public static boolean t = true;
public static void main(String[] argv) throws IOException {
glfwInit();
int prog = 0 , id=0;
long window = glfwCreateWindow(1920,
1080, "HI", 0 , 0);
glfwShowWindow(window);
glfwMakeContextCurrent(window);
GL.createCapabilities();
// glfwSetCursorPosCallback(window, mouseCallback = new mouse());
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
new man().createShader();
new man().bind();
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_COLOR_BUFFER_BIT);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glLoadIdentity();
glEnable(GL_PROJECTION_MATRIX);
glEnable(GL_PROJECTION);
new man().createprojection();
new man().createview();
glUseProgram(program);
new man().loadtoshader();
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vid);
glVertexPointer(3, GL_FLOAT , 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iid);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisable(GL_VERTEX_ARRAY);
}
}
public void createShader() throws IOException
{
StringBuilder vertex = new StringBuilder();
StringBuilder frag = new StringBuilder();
BufferedReader vert ,fragment;
vert = new BufferedReader(new FileReader("D:/work/opengl2/src/opengl2/vertexShader.txt"));
fragment = new BufferedReader(new FileReader("D:/work/opengl2/src/opengl2/frageShader.txt"));
//vertex Shader
String line, line2;
while ( (line = vert.readLine()) != null)
{
vertex.append(line).append('\n');
}
while ( (line2 = fragment.readLine()) != null)
{
frag.append(line2).append('\n');
}
//create and comile shaders
int vertexShader = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
GL20.glShaderSource(vertexShader, vertex);
GL20.glCompileShader(vertexShader);
int fragmentShader = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
GL20.glShaderSource(fragmentShader, frag);
GL20.glCompileShader(fragmentShader);
program = GL20.glCreateProgram();
GL20.glAttachShader(program, vertexShader);
GL20.glAttachShader(program, fragmentShader);
GL20.glBindAttribLocation(program, 0 , "postion");
GL20.glLinkProgram(program);
if (GL20.glGetProgrami(program, GL20.GL_LINK_STATUS) != 1)
{
System.err.println(GL20.glGetProgramInfoLog(program));
System.exit(1);
}
GL20.glValidateProgram(program);
}
public void bind()
{
float[] vertices = new float[128 * 128 * 3];
int[] indices = new int[6*(VERTEX_COUNT-1)*(VERTEX_COUNT-1)];
//generaete terrain
int vertexPointer = 0;
for(int i=0;i<VERTEX_COUNT;i++){
for(int j=0;j<VERTEX_COUNT;j++){
vertices[vertexPointer*3] = (float)j/((float)VERTEX_COUNT - 1) * SIZE;
vertices[vertexPointer*3+1] = 0;
vertices[vertexPointer*3+2] = (float)i/((float)VERTEX_COUNT - 1) * SIZE;
vertexPointer++;
}
}
int pointer = 0;
for(int gz=0;gz<VERTEX_COUNT-1;gz++){
for(int gx=0;gx<VERTEX_COUNT-1;gx++){
int topLeft = (gz*VERTEX_COUNT)+gx;
int topRight = topLeft + 1;
int bottomLeft = ((gz+1)*VERTEX_COUNT)+gx;
int bottomRight = bottomLeft + 1;
indices[pointer++] = topLeft;
indices[pointer++] = bottomLeft;
indices[pointer++] = topRight;
indices[pointer++] = topRight;
indices[pointer++] = bottomLeft;
indices[pointer++] = bottomRight;
}
}
//end generate terrain
FloatBuffer buffer = BufferUtils.createFloatBuffer(vertices.length);
buffer.put(vertices);
buffer.flip();
count = indices.length ;
vid = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vid);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
iid = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, iid);
IntBuffer indbuf = BufferUtils.createIntBuffer(indices.length);
indbuf.put(indices);
indbuf.flip();
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indbuf, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
public void createprojection()
{
float aspect = (float) 1920/1080;
float y_scale = (float) (1/Math.tan(Math.toRadians(fov/2f)));
float x_scale = y_scale / aspect;
float frustum_length = far - near;
projectionmatrix.m00 = x_scale;
projectionmatrix.m11 = y_scale;
projectionmatrix.m22 = -((far + near) / frustum_length);
projectionmatrix.m23 = -1;
projectionmatrix.m32 = -((2 * near * far) / frustum_length);
projectionmatrix.m33 = 0;
}
public void createview()
{
Vector3f modelPos = null;
Vector3f modelAngle = null;
Vector3f modelScale = null;
Vector3f camera = new Vector3f(0,1f,-2f);
modelPos = new Vector3f(0,0,0);
modelAngle = new Vector3f(0,0,0);
modelScale = new Vector3f(1, 1, 1);
modelMatrix.setIdentity();
Matrix4f.scale(modelScale, modelMatrix, modelMatrix);
Matrix4f.translate(modelPos, modelMatrix, modelMatrix);
Matrix4f.rotate((float) Math.toRadians(modelAngle.z), new Vector3f(0, 0, 1),
modelMatrix, modelMatrix);
Matrix4f.rotate((float) Math.toRadians(modelAngle.y), new Vector3f(0, 1, 0),
modelMatrix, modelMatrix);
Matrix4f.rotate((float) Math.toRadians(modelAngle.x), new Vector3f(1, 0, 0),
modelMatrix, modelMatrix);
Matrix4f.translate(camera, view, view);
}
public void loadtoshader()
{
int loc1 = glGetUniformLocation(program, "projection");
FloatBuffer matrixx = BufferUtils.createFloatBuffer(16);
projectionmatrix.store(matrixx);
matrixx.flip();
glUniformMatrix4fv(loc1, false,matrixx);
int loc2 = glGetUniformLocation(program, "view");
FloatBuffer matrixx2 = BufferUtils.createFloatBuffer(16);
view.store(matrixx2);
matrixx2.flip();
glUniformMatrix4fv(loc2, false,matrixx2);
int loc3 = glGetUniformLocation(program, "model");
FloatBuffer matrixx3 = BufferUtils.createFloatBuffer(16);
modelMatrix.store(matrixx3);
matrixx3.flip();
glUniformMatrix4fv(loc3, false,matrixx3);
}
}
class mouse extends GLFWCursorPosCallback
{
#Override
public void invoke(long arg0, double x, double y) {
// TODO Auto-generated method stub
System.out.println(x+ " "+ y );
}
}
Hi guys !
I want to generate a simple flat terrain in lwjgl but this code doesn't produce me anything. I am very new in this chapter so if you can explain why this code does nothing please do it! I am generating the terrain with the code shared by ThinMatrix , then i upload the vertices to the buffers and then render them in the main game loop . When i compile it , it shows me a black screen. I have searched for a lot of tutorials but I didn't find anything that can help me .
I see several issues with your code:
Issue Number 1: You are generating a new instance of the man class on every iteration of the loop. Create a single instance of the object outside of the loop and use it in the loop.
Issue Number 2: You are using the old, static pipeline OpenGL. Following ThinMatrix's tutorials, you should be using OpenGL 3 or newer. Everything should be going through shaders, rather than using the GL_PROJECTION_MATRIX and the likes of that.
Your program should look something like the following:
man instance = new man()
while (!glfwWindowShouldClose(window))
{
RENDER THE TERRAIN HERE
glfwPoll
glfwSwapBuffers
glClear
}
If you want some example code, I have a repository here that should help, as I used to watch ThinMatrix tutorials.
EDIT: SOLUTION
The vertex shader code should read:
gl_Position = projection * view * model * position;
My shaders: fragment
#version 330
in vec4 pos;
void main()
{
gl_FragColor = vec4 (pos);
}
vertex:
#version 330
attribute vec3 postion;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
out vec4 pos;
void main()
{
gl_Position = vec4(postion, 1.0) * projection * view * model;
pos = vec4(postion, 1.0) ;
}
I have updated my java code so it renders different colors base on the vertex position.

lwjgl 3 engine does not show anything

Im coding a Game with lwjgl3. I initially used lwjgl 2. but of major chanllenges, i switched to lwjgl3.
I walked through a couple tutorials and put together a gameloop with a window class and tried to implement the code i already had.
I had to change multiple things, had challenges like the slick util textureloader, but now im stuck:
Basically what i see is the Window, but nothing is displayed on it.
My Engine is fairly big by now, but i will try to implement the important methods. When you need more, i can post more.
I will post the Shaderfiles for entity and skybox (what im trying to display currently) too
And all i see is a Window with nothing displayed
MAIN CLASS
package main;
import static org.lwjgl.glfw.GLFW.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;
import entities.Camera;
import entities.Light;
import entities.Player;
import graphics.Window;
import graphics.models.RawModel;
import graphics.models.TexturedModel;
import graphics.renderEngine.Loader;
import graphics.renderEngine.MasterRenderer;
import graphics.renderEngine.OBJLoader;
import graphics.textures.ModelTexture;
import toolbox.Vector3f;
public class Main
{
private GLFWErrorCallback errorCallback = GLFWErrorCallback.createPrint(System.err);
private Window window;
private MasterRenderer renderer;
private Loader loader;
private int Width;
private int Height;
private boolean running = false;
private double delta;
List<Light> lights = new ArrayList<Light>();
Camera camera = null;
private Player player;
public Main()
{
init();
}
private void input()
{
glfwPollEvents();
if(window.shouldClose()) stop();
}
private void update()
{
renderer.setHeight(Height);
renderer.setWidth(Width);
renderer.setDelta(delta);
}
private void render()
{
renderer.processEntity(player);
renderer.render(lights, camera);
window.render();
}
private void run()
{
long lastTime = System.nanoTime();
long currentTime = lastTime;
long diff = 0;
long timer = System.currentTimeMillis();
double ns = 1000000000 / 60.0;
delta = 0.0;
double dfps = 1000000000 / 60.0;
double d = 0.0;
int fps = 0;
int ups = 0;
while(running)
{
currentTime = System.nanoTime();
diff = currentTime - lastTime;
delta += (diff)/ ns;
d += diff/dfps;
lastTime = currentTime;
while(delta >= 1.0)
{
input();
update();
ups++;
delta--;
}
if(d >- 1.0)
{
render();
fps++;
d = 0.0;
}
if(System.currentTimeMillis() > timer + 1000)
{
window.setTitle("Junker.5 | ups: "+ups+"| fps: "+fps+"");
ups = 0;
fps = 0;
timer += 1000;
}
}
cleanUp();
}
public void start()
{
if(running) return;
running = true;
run();
}
public void stop()
{
if(!running) return;
running = false;
}
private void init()
{
Width = 1280;
Height = 720;
glfwSetErrorCallback(errorCallback);
glfwInit();
window = new Window(Width, Height, "Junker.5");
GL.createCapabilities();
loader = new Loader();
renderer = new MasterRenderer(loader);
renderer.setHeight(Height);
renderer.setWidth(Width);
renderer.setDelta(delta);
RawModel playerShip = OBJLoader.loadObjModel("Puddle Jumper", loader);
TexturedModel playership = new TexturedModel(playerShip, ModelTexture.loadTexture("white"));
player = new Player(playership, new Vector3f(0, 0, -50),0,0,0,1);
lights.add(new Light(new Vector3f(0,1000,-5000), new Vector3f(0f,0.4f,5f)));
lights.add(new Light(new Vector3f(0,0,-10), new Vector3f(1,0,1), new Vector3f(1, 0.01f, 0.002f)));
try
{
camera = new Camera(player);
}
catch (IOException e)
{
e.printStackTrace();
}
}
private void cleanUp()
{
window.hide();
//guiRenderer.cleanUp();
renderer.cleanUp();
loader.cleanUp();
window.dispose();
}
public static void main(String[] args)
{
Main main = new Main();
main.start();
}
public int getWidth()
{
return window.getWidth();
}
public int getheight()
{
return window.getHeight();
}
public double getDelta()
{
return delta;
}
}
MASTER RENDERER CLASS
package graphics.renderEngine;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.lwjgl.opengl.GL11;
import entities.Camera;
import entities.Entity;
import entities.Light;
import entities.Player;
import graphics.models.RawModel;
import graphics.models.TexturedModel;
import graphics.shaders.StaticShader;
import graphics.shaders.TerrainShader;
import graphics.skybox.SkyboxRenderer;
import graphics.terrains.Terrain;
import graphics.textures.ModelTexture;
import toolbox.Matrix4f;
import toolbox.Vector3f;
public class MasterRenderer
{
private static final float FOV = 70;
private static final float NEAR_PLANE = 0.01f;
private static final float FAR_PLANE = 1000;
public int Width;
public double delta;
public int Height;
private Matrix4f projectionMatrix;
private StaticShader shader = new StaticShader();
private TerrainRenderer terrainRenderer;
private TerrainShader terrainShader = new TerrainShader();
private EntityRenderer renderer;
private Map<TexturedModel, List<Entity>> entities = new HashMap<TexturedModel, List<Entity>>();
private List<Terrain> terrains = new ArrayList<Terrain>();
private SkyboxRenderer skyboxRenderer ;
public MasterRenderer(Loader loader)
{
enableCulling();
createProjectionMatrix();
renderer = new EntityRenderer(shader, projectionMatrix);
terrainRenderer = new TerrainRenderer(terrainShader, projectionMatrix);
skyboxRenderer = new SkyboxRenderer(loader, projectionMatrix);
}
public static void enableCulling()
{
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glCullFace(GL11.GL_BACK);
}
public static void disableCullig()
{
GL11.glDisable(GL11.GL_CULL_FACE);
}
public void render(List<Light> lights, Camera camera)
{
prepare();
shader.start();
shader.loadLights(lights);
shader.loadViewMatrix(camera);
renderer.render(entities);
shader.stop();
terrainShader.start();
terrainShader.loadLights(lights);
terrainShader.loadViewMatrix(camera);
terrainRenderer.render(terrains);
terrainShader.stop();
skyboxRenderer.render(camera);
terrains.clear();
entities.clear();
}
public void processTerrain(Terrain terrain)
{
terrains.add(terrain);
}
public void processEntity(Entity entity)
{
TexturedModel entityModel = entity.getModel();
List<Entity> batch = entities.get(entityModel);
if(batch != null)
{
batch.add(entity);
}
else
{
List<Entity> newBatch = new ArrayList<Entity>();
newBatch.add(entity);
entities.put(entityModel, newBatch);
}
}
private void createProjectionMatrix()
{
float aspectRatio = (float) Width / (float) Height;
float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspectRatio);
float x_scale = y_scale / aspectRatio;
float frustum_length = FAR_PLANE - NEAR_PLANE;
projectionMatrix = new Matrix4f();
projectionMatrix.m00 = x_scale;
projectionMatrix.m11 = y_scale;
projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
projectionMatrix.m23 = -1;
projectionMatrix.m32 = -((2 * FAR_PLANE + NEAR_PLANE) / frustum_length);
projectionMatrix.m33 = 0;
}
public void prepare()
{
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(0.03f, 0f, 0.0f, 1);
}
public void cleanUp()
{
shader.cleanUp();
terrainShader.cleanUp();
}
public void setWidth(int width)
{
Width = width;
}
public void setHeight(int height)
{
Height = height;
}
public void setDelta(double delta)
{
this.delta = delta;
}
}
STATIC SHADER CLASS
package graphics.shaders;
import java.util.List;
import entities.Camera;
import entities.Light;
import toolbox.Maths;
import toolbox.Matrix4f;
import toolbox.Vector3f;
public class StaticShader extends ShaderProgram
{
public static final String VERTEX_FILE = "./Ressources/Shaders/VertexShader.shd";
public static final String FRAGMENT_FILE = "./Ressources/Shaders/FragmentShader.shd";
public static final int MAX_LIGHTS = 4;
private int location_transformationMatrix;
private int location_projectionMatrix;
private int location_viewMatrix;
private int location_lightPosition[];
private int location_lightColour[];
private int location_attenuation[];
private int location_shineDamper;
private int location_reflectivity;
private int location_useFakeLighting;
public StaticShader()
{
super(VERTEX_FILE, FRAGMENT_FILE);
}
#Override
protected void bindAttributes()
{
super.bindAttribute(0, "position");
super.bindAttribute(1, "textureCoords");
super.bindAttribute(2, "normal");
}
protected void getAllUniformLocations()
{
location_transformationMatrix = super.getUniformLocation("transformationMatrix");
location_projectionMatrix = super.getUniformLocation("projectionMatrix");
location_viewMatrix = super.getUniformLocation("viewMatrix");
location_shineDamper = super.getUniformLocation("shineDamper");
location_reflectivity = super.getUniformLocation("reflectivity");
location_useFakeLighting = super.getUniformLocation("useFakeLighting");
location_lightPosition = new int[MAX_LIGHTS];
location_attenuation = new int[MAX_LIGHTS];
location_lightColour = new int[MAX_LIGHTS];
for(int i = 0;i<MAX_LIGHTS;i++)
{
location_lightPosition[i] = super.getUniformLocation("lightPosition["+i+"]");
location_lightColour[i] = super.getUniformLocation("lightColour["+i+"]");
location_attenuation[i] = super.getUniformLocation("attenuation["+i+"]");
}
}
public void loadFakeLightingVariable(boolean useFake)
{
super.loadBoolean(location_useFakeLighting, useFake);
}
public void loadShineVariables(float damper, float reflectivity)
{
super.LoadFloat(location_shineDamper, damper);
super.LoadFloat(location_reflectivity, reflectivity);
}
public void loadTreansformationMatrix(Matrix4f matrix)
{
super.loadMatrix(location_transformationMatrix, matrix);
}
public void loadLights(List<Light> lights)
{
for(int i = 0;i<MAX_LIGHTS;i++)
{
if(i<lights.size())
{
super.LoadVector(location_lightPosition[i], lights.get(i).getPosition());
super.LoadVector(location_lightColour[i], lights.get(i).getColour());
super.LoadVector(location_attenuation[i], lights.get(i).getAttenuation());
}
else
{
super.LoadVector(location_lightPosition[i], new Vector3f(0,0,0));
super.LoadVector(location_lightColour[i], new Vector3f(0,0,0));
super.LoadVector(location_attenuation[i], new Vector3f(1,0,0));
}
}
}
public void loadViewMatrix(Camera camera)
{
Matrix4f viewMatrix = Maths.createViewMatrix(camera);
super.loadMatrix(location_viewMatrix, viewMatrix);
}
public void loadProjectionMatrix(Matrix4f projection)
{
super.loadMatrix(location_projectionMatrix, projection);
}
}
SHADERFILES:
FRAGMENT SHADER
#version 400 core
in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector[4];
in vec3 toCameraVector;
out vec4 out_Color;
uniform sampler2D textureSampler;
uniform vec3 lightColour[4];
uniform float shineDamper;
uniform float reflectivity;
uniform vec3 attenuation[4];
void main(void)
{
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitVectorToCamera = normalize(toCameraVector);
vec3 totalDiffuse = vec3(0.0);
vec3 totalSpecular = vec3(0.0);
for(int i=0;i<4;i++)
{
float distance = length(toLightVector[i]);
float attFactor = attenuation[i].x + (attenuation[i].y * distance) + (attenuation[i].z * distance * distance);
vec3 unitLightVector = normalize(toLightVector[i]);
float nDot1 = dot(unitNormal, unitLightVector);
float brightness = max(nDot1,0.0);
vec3 lightDirection = -unitLightVector;
vec3 reflectedLightDirection = reflect(lightDirection,unitNormal);
float specularFactor = dot(reflectedLightDirection, unitVectorToCamera);
specularFactor = max(specularFactor,0.0);
float dampedFactor = pow(specularFactor,shineDamper);
totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColour[i])/attFactor;
totalDiffuse = totalDiffuse + (brightness * lightColour[i])/attFactor;
}
totalDiffuse = max(totalDiffuse, 0.2);
vec4 textureColour = texture(textureSampler, pass_textureCoords);
if(textureColour.a<0.5)
{
discard;
}
out_Color = vec4(totalDiffuse,1.0) * texture(textureSampler, pass_textureCoords) + vec4(totalSpecular,1.0);
}
VERTEX SHADER
#version 400 core
in vec3 position;
in vec2 textureCoords;
in vec3 normal;
out vec2 pass_textureCoords;
out vec3 surfaceNormal;
out vec3 toLightVector[4];
out vec3 toCameraVector;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition[4];
uniform float useFakeLighting;
void main(void)
{
vec4 worldPosition = transformationMatrix * vec4(position,1.0);
gl_Position = projectionMatrix * viewMatrix * worldPosition;
pass_textureCoords = textureCoords;
vec3 actualNormal = normal;
if(useFakeLighting > 0.5)
{
actualNormal = vec3(0.0,1.0,0.0);
}
surfaceNormal = (transformationMatrix * vec4(actualNormal,0.0)).xyz;
for(int i=0;i<4;i++)
{
toLightVector[i] = lightPosition[i] - worldPosition.xyz;
}
toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz;
}
I have absolutely no idea what im doing wrong. If anyone wants to really help me more personal on this problem, feel free to contact me too.
Thank you soo much!
EDIT:
Yes, the Clearcolor works, thats part of why i am confused.
And before i worked ofer my lwjgl2 code to my new lwjgl3 code, the lwjgl3 window DID display simple graphics such as a 3d cube
Here is my window class
WINDOW
package graphics;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryUtil.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.system.MemoryUtil;
public class Window
{
private long window;
private int Width;
private int Height;
public Window(int width, int height, String title)
{
this.Width = width;
this.Height = height;
glfwDefaultWindowHints();
glfwWindowHint(GLFW_RESIZABLE, GL11.GL_FALSE);
glfwWindowHint(GLFW_VISIBLE, GL11.GL_TRUE);
//DECORATION
glfwWindowHint(GLFW_DECORATED, GL11.GL_TRUE);
glfwWindowHint(GLFW_FOCUSED, GL11.GL_TRUE);
window = glfwCreateWindow(Width,Height,"Junker.5",NULL,NULL);
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(
window,
(vidmode.width() - width) / 2,
(vidmode.height() - height) / 2
);
glfwMakeContextCurrent(window);
}
public void dispose()
{
glfwDestroyWindow(window);
}
public void hide()
{
glfwHideWindow(window);
}
public void render()
{
glfwSwapBuffers(window);
}
public void show()
{
glfwShowWindow(window);
}
public void setTitle(String title)
{
glfwSetWindowTitle(window, title);
}
public boolean shouldClose()
{
if(!glfwWindowShouldClose(window))
{
return false;
}
else
{
return true;
}
}
public int getWidth()
{
return Width;
}
public void setWidth(int width)
{
Width = width;
}
public int getHeight()
{
return Height;
}
public void setHeight(int height)
{
Height = height;
}
public void changecursor()
{
// Create the cursor object
//long cursor = GLFW.glfwCreateCursor(imageBuffer, 0, 0);
/*if (cursor == MemoryUtil.NULL)
throw new RuntimeException("Error creating cursor");
// Set the cursor on a window
GLFW.glfwSetCursor(window, cursor);*/
}
}
I did manage to fix the problem myself, atleast its displaying stuff now :)
I just hardcoded the Width and height right now. The method of doing a setHeight() in the Main class must have angried the gods of my createProjectionMatrix() function. However, id would be awesome to know how to do this dynamic for future purposes

Android bytedeco javacpp ffmpeg decode h264 bytes to yuv and render with openGL ES 2.0. Wrong colors

there! I try to display a video stream, which comes from server as byte array.
Data in this array is h264 encoded image and i decode it with bytedeco javacpp-presets library in this way:
public class DMDecoder {
private static final String LOG_TAG = "DMDecoder";
private AVCodec avCodec;
private AVCodecContext avCodecContext;
private AVFrame avFrame;
private AVPacket avPacket;
private boolean wasIFrame;
private long IFrameTimeStampMs;
private int maxFps;
private int codecId;
private DMDecoderCallback callback;
public DMDecoder(DMDecoderCallback cb) {
this.callback = cb;
this.codecId = AV_CODEC_ID_H264;
avcodec_register_all();
restart();
}
public void restart() {
stop();
start();
}
public void stop() {
frames = 0;
if (avCodecContext != null) {
avcodec_close(avCodecContext);
avcodec_free_context(avCodecContext);
avCodecContext = null;
}
if (avCodec != null) {
av_free(avCodec);
avCodec = null;
}
if (avFrame != null) {
av_frame_free(avFrame);
avFrame = null;
}
if (avPacket != null) {
av_free_packet(avPacket);
avPacket = null;
}
}
public void start() {
avCodec = avcodec_find_decoder(codecId);
avCodecContext = avcodec_alloc_context3(avCodec);
AVDictionary opts = new AVDictionary();
avcodec_open2(avCodecContext, avCodec, opts);
avFrame = av_frame_alloc();
avPacket = new AVPacket();
av_init_packet(avPacket);
}
public VideoFrame decode(byte[] data, int dataOffset, int dataSize) {
avPacket.pts(AV_NOPTS_VALUE);
avPacket.dts(AV_NOPTS_VALUE);
avPacket.data(new BytePointer(data).position(dataOffset));
avPacket.size(dataSize);
avPacket.pos(-1);
IntBuffer gotPicture = IntBuffer.allocate(1);
int processedBytes = avcodec_decode_video2(
avCodecContext, avFrame, gotPicture, avPacket);
if (avFrame.width() == 0 || avFrame.height() == 0) return null;
VideoFrame frame = new VideoFrame();
frame.colorPlane0 = new byte[avFrame.width() * avFrame.height()];
frame.colorPlane1 = new byte[avFrame.width() / 2 * avFrame.height() / 2];
frame.colorPlane2 = new byte[avFrame.width() / 2 * avFrame.height() / 2];
if (avFrame.data(0) != null) avFrame.data(0).get(frame.colorPlane0);
if (avFrame.data(1) != null) avFrame.data(1).get(frame.colorPlane1);
if (avFrame.data(2) != null) avFrame.data(2).get(frame.colorPlane2);
frame.lineSize0 = avFrame.width();
frame.lineSize1 = avFrame.width() / 2;
frame.lineSize2 = avFrame.width() / 2;
frame.width = avFrame.width();
frame.height = avFrame.height();
return frame;
}
}
VideoFrame class is just simple POJO:
public class VideoFrame {
public byte[] colorPlane0;
public byte[] colorPlane1;
public byte[] colorPlane2;
public int lineSize0;
public int lineSize1;
public int lineSize2;
public int width;
public int height;
public long presentationTime;
}
After decoding i send this frame to my GLRenderer class
public class GLRenderer implements GLSurfaceView.Renderer {
private static final String LOG_TAG = "GLRenderer";
private TexturePlane plane;
private ConcurrentLinkedQueue<VideoFrame> frames;
private int maxFps = 30;
private VideoFrame currentFrame;
private long startTime, endTime;
private int viewWidth, viewHeight;
private boolean isFirstFrameProcessed;
public GLRenderer(int viewWidth, int viewHeight) {
frames = new ConcurrentLinkedQueue<>();
this.viewWidth = viewWidth;
this.viewHeight = viewHeight;
}
// 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];
#Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
plane = new TexturePlane();
}
public void setMaxFps(int maxFps) {
this.maxFps = maxFps;
}
#Override
public void onDrawFrame(GL10 unused) {
// Draw background color
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);
if (!isFirstFrameProcessed) checkViewPort(viewWidth, viewHeight);
if (maxFps > 0 && startTime > 0) {
endTime = System.currentTimeMillis();
long time = endTime - startTime;
//
long wantedTime = 1000 / maxFps;
//
long wait;
if (time < wantedTime) {
wait = wantedTime - time;
//
try {
Thread.sleep(wait);
} catch (InterruptedException e) {
Log.e(LOG_TAG, "thread interrupted exception");
}
}
}
startTime = System.currentTimeMillis();
tick();
plane.draw(mMVPMatrix);
}
private void updateFrame(VideoFrame frame) {
plane.updateTexture(frame.colorPlane0, frame.width, frame.height, 0);
plane.updateTexture(frame.colorPlane1, frame.width / 2, frame.height / 2, 1);
plane.updateTexture(frame.colorPlane2, frame.width / 2, frame.height / 2, 2);
plane.setTextureWidth(frame.width);
plane.setTextureHeight(frame.height);
}
private void tick() {
if (frames.isEmpty()) return;
VideoFrame frame = frames.peek();
if (frame == null) return;
long tms = System.currentTimeMillis();
if (frame.presentationTime <= tms) {
updateFrame(frame);
currentFrame = frame;
frames.remove(frame);
}
}
#Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
checkViewPort(width, height);
viewWidth = width;
viewHeight = height;
plane.setTextureWidth(width);
plane.setTextureHeight(height);
}
private void checkViewPort(int width, int height) {
float viewRatio = (float) width / height;
if (currentFrame != null) {
float targetRatio = (float) currentFrame.width / currentFrame.height;
int x, y, newWidth, newHeight;
if (targetRatio > viewRatio) {
newWidth = width;
newHeight = (int) (width / targetRatio);
x = 0;
y = (height - newHeight) / 2;
} else {
newHeight = height;
newWidth = (int) (height * targetRatio);
y = 0;
x = (width - newWidth) / 2;
}
GLES20.glViewport(x, y, newWidth, newHeight);
} else {
GLES20.glViewport(0, 0, width, height);
}
Matrix.frustumM(mProjectionMatrix, 0, 1, -1, -1, 1, 3, 4);
}
public void addFrame(VideoFrame frame) {
if (frame != null) {
frames.add(frame);
}
}
}
GLRenderer works with simple openGL polygon, on which i draw all textures
public class TexturePlane {
private static final String LOG_TAG = "TexturePlane";
private final String vertexShaderCode = "" +
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec2 a_TexCoordinate;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
" v_TexCoordinate = a_TexCoordinate;" +
"}";
private final String fragmentShaderCode = "" +
"precision mediump float;" +
"varying vec2 v_TexCoordinate;" +
"uniform sampler2D s_texture_y;" +
"uniform sampler2D s_texture_u;" +
"uniform sampler2D s_texture_v;" +
"void main() {" +
" float y = texture2D(s_texture_y, v_TexCoordinate).r;" +
" float u = texture2D(s_texture_u, v_TexCoordinate).r - 0.5;" +
" float v = texture2D(s_texture_v, v_TexCoordinate).r - 0.5;" +
" float r = y + 1.13983 * v;" +
" float g = y - 0.39465 * u - 0.58060 * v;" +
" float b = y + 2.03211 * u;" +
" gl_FragColor = vec4(r, g, b, 1.0);" +
"}";
private final FloatBuffer vertexBuffer;
private final FloatBuffer textureBuffer;
private final ShortBuffer drawListBuffer;
private final int mProgram;
private int mPositionHandle;
private int mMVPMatrixHandle;
// number of coordinates per vertex in this array
private static final int COORDS_PER_VERTEX = 3;
private static final int COORDS_PER_TEXTURE = 2;
private static float squareCoords[] = {
-1f, 1f, 0.0f,
-1f, -1f, 0.0f,
1f, -1f, 0.0f,
1f, 1f, 0.0f
};
private static float uvs[] = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
private final short drawOrder[] = {0, 1, 2, 0, 2, 3}; // order to draw vertices
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private int textureWidth = 640;
private int textureHeight = 480;
private int yTextureUniformHandle;
private int uTextureUniformHandle;
private int vTextureUniformHandle;
private int yTextureHandle;
private int uTextureHandle;
private int vTextureHandle;
private int mTextureCoordinateHandle;
public void setTextureWidth(int textureWidth) {
this.textureWidth = textureWidth;
}
public int getTextureWidth() {
return textureWidth;
}
public void setTextureHeight(int textureHeight) {
this.textureHeight = textureHeight;
}
public int getTextureHeight() {
return textureHeight;
}
/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
public TexturePlane() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer tbb = ByteBuffer.allocateDirect(uvs.length * 4);
tbb.order(ByteOrder.nativeOrder());
textureBuffer = tbb.asFloatBuffer();
textureBuffer.put(uvs);
textureBuffer.position(0);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
compileShaders();
setupTextures();
}
public void setupTextures() {
yTextureHandle = setupTexture(null, textureWidth, textureHeight, 0);
uTextureHandle = setupTexture(null, textureWidth, textureHeight, 1);
vTextureHandle = setupTexture(null, textureWidth, textureHeight, 2);
}
public int setupTexture(ByteBuffer data, int width, int height, int index) {
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0) {
// Bind to the texture in OpenGL
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + index);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
updateTexture(data, width, height, index);
// Set filtering
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
// Set wrapping mode
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
}
if (textureHandle[0] == 0) {
Log.e(LOG_TAG, "Error loading texture.");
}
return textureHandle[0];
}
public void updateTexture(byte[] data, int width, int height, int index) {
if (data == null) {
if (width == 0 || height == 0) {
width = textureWidth;
height = textureHeight;
}
data = new byte[width * height];
if (index == 0) {
Arrays.fill(data, y);
} else if (index == 1) {
Arrays.fill(data, u);
} else {
Arrays.fill(data, v);
}
}
byteBuffer.wrap(data);
byteBuffer.position(0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + index);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
width, height, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, byteBuffer);
}
private void compileShaders() {
// prepare shaders and OpenGL program
int vertexShader = loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables
checkGlError("glLinkProgram");
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
yTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "s_texture_y");
uTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "s_Texture_u");
vTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "s_Texture_v");
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
checkGlError("glGetUniformLocation");
}
/**
* Utility method for compiling a OpenGL shader.
* <p/>
* <p><strong>Note:</strong> When developing shaders, use the checkGlError()
* method to debug shader coding errors.</p>
*
* #param type - Vertex or fragment shader type.
* #param shaderCode - String containing the shader code.
* #return - Returns an id for the shader.
*/
public int loadShader(int type, String shaderCode) {
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
/**
* Utility method for debugging OpenGL calls. Provide the name of the call
* just after making it:
* <p/>
* <pre>
* mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
* MyGLRenderer.checkGlError("glGetUniformLocation");</pre>
*
* If the operation is not successful, the check throws an error.
*
* #param glOperation - Name of the OpenGL call to check.
*/
public void checkGlError(String glOperation) {
int error;
String errorString;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
errorString = GLU.gluErrorString(error);
String message = glOperation + ": glError " + error + ": " + errorString;
Log.e(LOG_TAG, message);
throw new RuntimeException(message);
}
}
public void draw(float[] mvpMatrix) {
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GLES20.glVertexAttribPointer(
mTextureCoordinateHandle, COORDS_PER_TEXTURE,
GLES20.GL_FLOAT, false,
0, textureBuffer);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
checkGlError("glUniformMatrix4fv");
GLES20.glUniform1i(yTextureUniformHandle, 0);
GLES20.glUniform1i(uTextureUniformHandle, 1);
GLES20.glUniform1i(vTextureUniformHandle, 2);
// Draw the square
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
}
}
But i have a problem there. My GL surface display image with wrong colors. image
What i'm doing wrong?
UPDATE:
As Ronald S. Bultje say, i added glBindTexture(...) function in my code. And now updateTexture(...) method looks like this:
public void updateTexture(byte[] data, int width, int height, int index) {
if (data == null) {
if (width == 0 || height == 0) {
width = textureWidth;
height = textureHeight;
}
data = new byte[width * height];
if (index == 0) {
Arrays.fill(data, y);
} else if (index == 1) {
Arrays.fill(data, u);
} else {
Arrays.fill(data, v);
}
}
byteBuffer.wrap(data);
byteBuffer.position(0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + index);
int textureHandle = index == 0 ? yTextureHandle : index == 1 ? uTextureHandle : vTextureHandle;
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
width, height, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, byteBuffer);
}
Your updateTexture() function doesn't call GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[index]); after calling GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + index);
[edit] actually given your code, it would be index==0?yTextureHandle:index==1?uTextureHandle?vTextureHandle, I'm sure you can figure out how to refactor your code to make this easier.

Why it doesn't draw an animated curve?

This is my class which I found on the Internet. It was originally an applet but I don't want to use it as an applet so I changed some methods (such as init() to a constructor).
However, it doesn't work. Would you please help me?
SignInFrame Frame:
public class SignInFrame extends javax.swing.JFrame {
Panel panel;
/** Creates new form SignInFrame */
public SignInFrame() {
initComponents();
}
public void init() {
getContentPane().add(panel = new Panel());
}
public void start() {
panel.start();
}
public void stop() {
panel.stop();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new SignInFrame().setVisible(true);
}
});
}}
Panel Dialog:
package ClientGUI;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
/**
*
* #author ICC
*/
public class Panel extends javax.swing.JPanel implements Runnable{
private Thread thread;
private BufferedImage bimg;
private static final int NUMPTS = 6;
// solid line stoke
protected BasicStroke solid = new BasicStroke(10.0f,
BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
// dashed line stroke
protected BasicStroke dashed = new BasicStroke(10.0f,
BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 10, new float[] {5}, 0);
private float animpts[] = new float[NUMPTS * 2];
private float deltas[] = new float[NUMPTS * 2];
protected Paint fillPaint, drawPaint;
// indicates whether or not to fill shape
protected boolean doFill = true;
// indicates whether or not to draw shape
protected boolean doDraw = true;
protected GradientPaint gradient;
protected BasicStroke stroke;
public Panel() {
setBackground(Color.white);
gradient = new GradientPaint(0,0,Color.red,200,200,Color.yellow);
fillPaint = gradient;
drawPaint = Color.blue;
stroke = solid;
}
// generates new points for the path
public void animate(float[] pts, float[] deltas, int i, int limit) {
float newpt = pts[i] + deltas[i];
if (newpt <= 0) {
newpt = -newpt;
deltas[i] = (float) (Math.random() * 4.0 + 2.0);
} else if (newpt >= (float) limit) {
newpt = 2.0f * limit - newpt;
deltas[i] = - (float) (Math.random() * 4.0 + 2.0);
}
pts[i] = newpt;
}
/*
* generates random points with the specified surface width
* and height for the path
*/
public void reset(int w, int h) {
for (int i = 0; i < animpts.length; i += 2) {
animpts[i + 0] = (float) (Math.random() * w);
animpts[i + 1] = (float) (Math.random() * h);
deltas[i + 0] = (float) (Math.random() * 6.0 + 4.0);
deltas[i + 1] = (float) (Math.random() * 6.0 + 4.0);
if (animpts[i + 0] > w / 2.0f) {
deltas[i + 0] = -deltas[i + 0];
}
if (animpts[i + 1] > h / 2.0f) {
deltas[i + 1] = -deltas[i + 1];
}
}
gradient = new GradientPaint(0,0,Color.red,w*.7f,h*.7f,Color.yellow);
}
// calls animate for every point in animpts
public void step(int w, int h) {
for (int i = 0; i < animpts.length; i += 2) {
animate(animpts, deltas, i + 0, w);
animate(animpts, deltas, i + 1, h);
}
}
// sets the points of the path and draws and fills the path
public void drawDemo(int w, int h, Graphics2D g2) {
float[] ctrlpts = animpts;
int len = ctrlpts.length;
float prevx = ctrlpts[len - 2];
float prevy = ctrlpts[len - 1];
float curx = ctrlpts[0];
float cury = ctrlpts[1];
float midx = (curx + prevx) / 2.0f;
float midy = (cury + prevy) / 2.0f;
GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO);
gp.moveTo(midx, midy);
for (int i = 2; i <= ctrlpts.length; i += 2) {
float x1 = (midx + curx) / 2.0f;
float y1 = (midy + cury) / 2.0f;
prevx = curx;
prevy = cury;
if (i < ctrlpts.length) {
curx = ctrlpts[i + 0];
cury = ctrlpts[i + 1];
} else {
curx = ctrlpts[0];
cury = ctrlpts[1];
}
midx = (curx + prevx) / 2.0f;
midy = (cury + prevy) / 2.0f;
float x2 = (prevx + midx) / 2.0f;
float y2 = (prevy + midy) / 2.0f;
gp.curveTo(x1, y1, x2, y2, midx, midy);
}
gp.closePath();
if (doDraw) {
g2.setPaint(drawPaint);
g2.setStroke(stroke);
g2.draw(gp);
}
if (doFill) {
if (fillPaint instanceof GradientPaint) {
fillPaint = gradient;
}
g2.setPaint(fillPaint);
g2.fill(gp);
}
}
public Graphics2D createGraphics2D(int w, int h) {
Graphics2D g2 = null;
if (bimg == null || bimg.getWidth() != w || bimg.getHeight() != h) {
bimg = (BufferedImage) createImage(w, h);
reset(w, h);
}
g2 = bimg.createGraphics();
g2.setBackground(getBackground());
g2.clearRect(0, 0, w, h);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
return g2;
}
public void paint(Graphics g) {
Dimension d = getSize();
step(d.width, d.height);
Graphics2D g2 = createGraphics2D(d.width, d.height);
drawDemo(d.width, d.height, g2);
g2.dispose();
if (bimg != null) {
g.drawImage(bimg, 0, 0, this);
}
}
public void start() {
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
public synchronized void stop() {
thread = null;
}
public void run() {
Thread me = Thread.currentThread();
while (thread == me) {
repaint();
try {
Thread.sleep(10);
} catch (Exception e) { break; }
}
thread = null;
}
public static void main(String argv[]) {
SignInFrame n = new SignInFrame();
n.start();
}}
In your SignInFrame constructor, you call initComponents(), but that does not exist. I think you mean to call init(). Also your JFrame does not have a size set, when I ran this under linux (Java 1.6), it worked but was tiny, you should add a setSize call.
Try it with these edits:
public class SignInFrame extends javax.swing.JFrame {
Panel panel;
/** Creates new form SignInFrame */
public SignInFrame() {
setSize (600,600);
init();
}
public void init() {
getContentPane().add(panel = new Panel());
start();
}
public void start() {
panel.start();
}
public void stop() {
panel.stop();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new SignInFrame().setVisible(true);
}
});
}
}

Categories

Resources