I need to make a rubik cube in JavaFX not using the standard libs and SceneBulider. The question is - I have a texture that I need to wrap around the cube. Using this:
Skinning custom 3D cube in javafx 8
and this Create a cube using different textures in JavaFX
was not able to get any result.
Anyway here's my Controller.
import com.sun.javafx.geom.transform.GeneralTransform3D;
import javafx.fxml.FXML;
import javafx.scene.*;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
public class Controller{
/* double mousePosX;
double mousePosY;
double mouseOldX;
double mouseOldY;
Rotate rotateX = new Rotate(30, 0, 0, 0, Rotate.X_AXIS);
Rotate rotateY = new Rotate(20, 0, 0, 0, Rotate.Y_AXIS);*/
#FXML
Camera camera = new PerspectiveCamera(true);
#FXML
private Box rubik;
#FXML
private AnchorPane anchor;
#FXML
private MeshView mesh;
#FXML
private AmbientLight ambientlight;
private void paintCube()
{
Image dieImage = new Image(getClass().getResourceAsStream("textura.png"));
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(dieImage);
ambientlight.setColor(Color.WHITE);
float hw = 300/2f;
float hh = 300/2f;
float hd = 300/2f;
float points[] =
{
0, 0, 300, //P0
300, 0, 300, //P1
0, 300, 300, //P2
300, 300, 300, //P3
0, 0, 0, //P4
300, 0, 0, //P5
0, 300, 0, //P6
300, 300, 0 //P7
};
float tex[] =
{
0.25f, 0, //T0
0.5f, 0, //T1
0, 0.25f, //T2
0.25f, 0.25f, //T3
0.5f, 0.25f, //T4
0.75f, 0.25f, //T5
1, 0.25f, //T6
0, 0.5f, //T7
0.25f, 0.5f, //T8
0.5f, 0.5f, //T9
0.75f, 0.5f, //T10
1, 0.5f, //T11
0.25f, 0.75f, //T12
0.5f, 0.75f //T13
};
int faces[] =
{
5,1,4,0,0,3 //P5,T1 ,P4,T0 ,P0,T3
,5,1,0,3,1,4 //P5,T1 ,P0,T3 ,P1,T4
,0,3,4,2,6,7 //P0,T3 ,P4,T2 ,P6,T7
,0,3,6,7,2,8 //P0,T3 ,P6,T7 ,P2,T8
,1,4,0,3,2,8 //P1,T4 ,P0,T3 ,P2,T8
,1,4,2,8,3,9 //P1,T4 ,P2,T8 ,P3,T9
,5,5,1,4,3,9 //P5,T5 ,P1,T4 ,P3,T9
,5,5,3,9,7,10 //P5,T5 ,P3,T9 ,P7,T10
,4,6,5,5,7,10 //P4,T6 ,P5,T5 ,P7,T10
,4,6,7,10,6,11 //P4,T6 ,P7,T10 ,P6,T11
,3,9,2,8,6,12 //P3,T9 ,P2,T8 ,P6,T12
,3,9,6,12,7,13 //P3,T9 ,P6,T12 ,P7,T13
};
TriangleMesh mesh1 = new TriangleMesh();
mesh1.getPoints().addAll(points);
mesh1.getTexCoords().addAll(tex);
mesh1.getFaces().addAll(faces);
//mesh = new MeshView(mesh1);
//mesh.setMaterial(material);
mesh.setMesh(mesh1);
rubik.setMaterial(material);
}
#FXML
public void initialize()
{
Rotate cameraRotateX, cameraRotateY, cameraRotateZ;
Translate cameraTranslate;
cameraRotateX = new Rotate(10, Rotate.X_AXIS);
cameraRotateY = new Rotate(10, Rotate.Y_AXIS);
cameraRotateZ = new Rotate(0, Rotate.Z_AXIS);
rubik.getTransforms().addAll(
cameraRotateX,
cameraRotateY,
cameraRotateZ);
// Rotate rotateX = new Rotate(30, 0, 0, 0, Rotate.X_AXIS);
// Rotate rotateY = new Rotate(20, 0, 0, 0, Rotate.Y_AXIS);
//rubik.setRotate(45);
paintCube();
}
/* #FXML
public void klik(MouseEvent mouseEvent) {
mouseOldX = mouseEvent.getX();
mouseOldY = mouseEvent.getY();
}
#FXML
public void gowno(MouseEvent mouseEvent) {
mousePosX = mouseEvent.getX();
mousePosY = mouseEvent.getY();
rotateX.setAngle(rotateX.getAngle()-(mousePosY - mouseOldY));
rotateY.setAngle(rotateY.getAngle()+(mousePosX - mouseOldX));
mouseOldX = mousePosX;
mouseOldY = mousePosY;
}
*/
}
the cube is 300/300/300.
Related
I am currently having issues with trying to render two textures onto two totally separate objects through a single vertex, and fragment shader. The issue seems to lie in trying to index, and bind the two textures onto their own objects. In trying to index and bind the textures, the smaller index will always appear onto both objects.
Can someone help me, or at least push me into the right direction?
here is my code for the main class, the renderer, and the fragment shader.
(feel free to request more code)
main:
import Engine.IO.Image;
import Engine.IO.Input;
import Engine.IO.Window;
import Engine.graphics.*;
import Engine.maths.Vector2f;
import Engine.maths.Vector3f;
import Engine.objects.Camera;
import Engine.objects.GameObject;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL13;
public class Main implements Runnable {
public Thread game;
public Window window;
public Renderer renderer;
public Shader shader;
public final int WIDTH = 1280, HEIGHT = 720;
private String[] textureImageNames = {"nice_dude.jpg", "color.jpg", "pepe.jpg"};
public GameObject thing1 = new GameObject(new Vector3f(-1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1), new Mesh(new Vertex[]{
new Vertex(new Vector3f(-0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,0.0f)),
new Vertex(new Vector3f(0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,0.0f)),
new Vertex(new Vector3f(0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,1.0f)),
new Vertex(new Vector3f(-0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,1.0f))
}, new int[]{
0, 1, 2, 0, 3, 2
}), new Material(textureImageNames[0]));
public GameObject thing2 = new GameObject(new Vector3f(1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1), new Mesh(new Vertex[]{
new Vertex(new Vector3f(-0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,0.0f)),
new Vertex(new Vector3f(0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,0.0f)),
new Vertex(new Vector3f(0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,1.0f)),
new Vertex(new Vector3f(-0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,1.0f))
}, new int[]{
0, 1, 2, 0, 3, 2
}), new Material(textureImageNames[2]));
public Camera camera = new Camera(new Vector3f(0, 0, 1), new Vector3f(0, 0,0));
public void start(){
game = new Thread(this,"game");
game.start();
}
public void init(){
System.out.println("Initializing Game!");
window = new Window(WIDTH, HEIGHT, "Game");
shader = new Shader("/shaders/mainVertex.glsl", "/shaders/mainFragment.glsl");
window.setBackgroundColor(0.0f, 0.5f, 0.0f);
window.create();
thing1.getMesh().create();
thing2.getMesh().create();
thing1.getMaterial().create(new Image());
thing2.getMaterial().create(new Image());
shader.create();
renderer = new Renderer(window, shader);
renderer.renderMesh();
renderer.enableShaderProgram();
renderer.bindVAO(thing1);
renderer.bindVAO(thing2);
renderer.setUniformIndex(thing1,"tex", GL13.GL_TEXTURE0);
renderer.setUniformIndex(thing2,"tex2", GL13.GL_TEXTURE1);
}
public void run(){
init();
while(!window.shouldClose() && !Input.isKeyDown(GLFW.GLFW_KEY_ESCAPE)){
update();
render();
if(Input.isKeyDown(GLFW.GLFW_KEY_F11)){window.setFullscreen(!window.isFullscreen());}
}
close();
}
private void update(){
//System.out.println("updating Game!");
window.update();
camera.update();
}
private void render(){
renderer.updateRenderer(thing1);
renderer.updateRenderer(thing2);
renderer.renderCamera(camera);
window.swapBuffers();
}
private void close(){
window.destroy();
thing1.getMesh().destroy();
thing1.destroyMaterial();
thing2.getMesh().destroy();
thing2.destroyMaterial();
shader.destroy();
renderer.destroyRenderer();
}
public static void main(String[] args){
new Main().start();
}
}
render class:
package Engine.graphics;
import Engine.IO.Window;
import Engine.maths.Matrix4f;
import Engine.objects.Camera;
import Engine.objects.GameObject;
import org.lwjgl.opengl.*;
public class Renderer {
private Shader shader;
private Window window;
public Renderer(Window window, Shader shader){
this.shader = shader;
this.window = window;
}
public void renderMesh() {
GL30.glEnableVertexAttribArray(0);
GL30.glEnableVertexAttribArray(1);
GL30.glEnableVertexAttribArray(2);
}
public void enableShaderProgram(){
shader.bind();
}
public void bindVAO(GameObject object){
GL30.glBindVertexArray(object.getMesh().getVAO());
}
public void setUniformIndex(GameObject object, String textureName, int index){
GL13.glActiveTexture(index);
shader.setUniform(textureName, index);
GL13.glBindTexture(GL11.GL_TEXTURE_2D, object.getMaterial().getTextureID());
}
public void updateRenderer(GameObject object){
GL11.glDrawElements(GL11.GL_TRIANGLES, object.getMesh().getIndices().length, GL11.GL_UNSIGNED_INT, 0);
shader.setUniform("model", Matrix4f.transform(object.getPosition(), object.getRotation(), object.getScale()));
shader.setUniform("projection", window.getProjectionMatrix());
}
public void renderCamera(Camera camera){
shader.setUniform("view", Matrix4f.view(camera.getPosition(), camera.getRotation()));
}
public void destroyRenderer(){
shader.unBind();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL30.glDisableVertexAttribArray(0);
GL30.glDisableVertexAttribArray(1);
GL30.glDisableVertexAttribArray(2);
GL30.glBindVertexArray(0);
}
}
fragment shader:
#version 460 core
in vec3 passColor;
in vec2 passTextureCoord;
out vec4 outColor;
uniform sampler2D tex;
uniform sampler2D tex2;
void main(){
outColor = texture(tex, passTextureCoord);
outColor = texture(tex2, passTextureCoord);
}
The value which has to be set to the texture sampler uniform is the index of the texture unit rather then the texture unit constant (e.g.: 0 for GL13.GL_TEXTURE0 and 1 for GL13.GL_TEXTURE1):
public void setUniformIndex(GameObject object, String textureName, int unit, int index){
shader.setUniform(textureName, index);
GL13.glActiveTexture(unit);
GL13.glBindTexture(GL11.GL_TEXTURE_2D, object.getMaterial().getTextureID());
}
OpenGL is a state engine. Binding a VAO and or a texture object changes a global state. It is not possible to bind 2 objects at once. Only the last object which was bound is stated. You have to bind the Vertex Array Object and the texture object before the draw call:
private void render(){
renderer.bindVAO(thing1);
renderer.setUniformIndex(thing1,"tex", GL13.GL_TEXTURE0, 0);
renderer.updateRenderer(thing1);
renderer.bindVAO(thing2);
renderer.setUniformIndex(thing2,"tex2", GL13.GL_TEXTURE1, 1);
renderer.updateRenderer(thing2);
renderer.renderCamera(camera);
window.swapBuffers();
}
Using java3d, how can I colorize not on a per vertex base but on a per face base?
I try to learn about java3d but what Shape3d I did produce does not look as expected.
I want to colorize different triangles in different colors, but I don't see how to do it.
Texture looks like an overkill, and what's more, I haven't mastered this part at all.
As far as I've seen Materials work on a complete GeometryArray, so are no good here.
Per vertex colors won't do the trick.
I fond the solution. "per vertex colors" really are per vertex reference, so each vertex can have a different color for each of its faces.
Here is a working example (regrettably not very small):
package examples;
import javax.media.j3d.Alpha;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.IndexedTriangleArray;
import javax.media.j3d.Node;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.media.j3d.ViewPlatform;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.geometry.NormalGenerator;
import com.sun.j3d.utils.universe.MultiTransformGroup;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;
public class Example {
public static void main(final String[] args) {
new Example();
}
public Example() {
final SimpleUniverse universe = new SimpleUniverse();
final BranchGroup group = new BranchGroup();
final TransformGroup tg = new TransformGroup();
final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
final Node blob = createMonster();
{ //to enable rotation
tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
}
// Create rotation to see all sides of the object
final Transform3D btrans = new Transform3D();
btrans.rotX(1);
final Transform3D ztrans = new Transform3D();
ztrans.rotZ(-1);
btrans.mul(ztrans);
final RotationInterpolator ri = createRotation(tg, bounds, btrans, 7000);
tg.addChild(ri);
tg.addChild(blob);
//
group.addChild(tg);
//
addLight(group, new Color3f(1f, 1f, 0f), new Vector3f(4.0f, +7.0f, -12.0f));
addLight(group, new Color3f(1f, 1f, 1f));
//
final ViewingPlatform viewingPlatform = universe.getViewingPlatform();
final ViewPlatform view = viewingPlatform.getViewPlatform();
view.setViewAttachPolicy(View.NOMINAL_SCREEN);
viewingPlatform.setNominalViewingTransform();
final MultiTransformGroup mtg = viewingPlatform.getMultiTransformGroup();
final TransformGroup vtg = mtg.getTransformGroup(0);
final Transform3D t1 = btrans;
vtg.getTransform(t1);
t1.setScale(2);
vtg.setTransform(t1);
group.compile();
// add the group of objects to the Universe
universe.addBranchGraph(group);
}
private Node createMonster() {
final Shape3D child = createShape();
final Appearance fillAppNode = new Appearance();
final PolygonAttributes pAtt = new PolygonAttributes();
// avoid trouble with clockwise faces
pAtt.setCullFace(PolygonAttributes.CULL_NONE);
pAtt.setBackFaceNormalFlip(true);
fillAppNode.setPolygonAttributes(pAtt);
child.setAppearance(fillAppNode);
return child;
}
private Shape3D createShape() {
final Point3d[] points = new Point3d[] {//
new Point3d(-1, 1, 0), //
new Point3d(1, 1, 0), //
new Point3d(1, -1, 0), //
new Point3d(-1, -1, 0), //
new Point3d(0, 0, 1), //
};
final int[] idxs = new int[] {// the triangle faces
0, 1, 2,//
2, 3, 0,//
1, 0, 4,//
1, 2, 4,//
2, 3, 4,//
3, 0, 4 };
final IndexedTriangleArray ita = new IndexedTriangleArray(points.length, GeometryArray.COORDINATES
| GeometryArray.COLOR_3, idxs.length);
ita.setCoordinates(0, points);
ita.setCoordinateIndices(0, idxs);
//per vertex colors really are per vertex reference
//so each vertex can have a different color for each of its faces
final Color3f[] colors = new Color3f[] {//
new Color3f(1, 0, 1),//
new Color3f(0, 1, 0),//
new Color3f(0, 0, 1),//
new Color3f(1, 1, 0),//
new Color3f(1, 1, 1),//
};
ita.setColors(0, colors);
ita.setColorIndices(0, idxs);
ita.setColorIndices(0, new int[] { 0, 0, 0, 1, 1, 1 });
//
final GeometryInfo gi = new GeometryInfo(ita);
//also generate normal vectors so that the surface can be light
final NormalGenerator normalGenerator = new NormalGenerator();
normalGenerator.generateNormals(gi);
final GeometryArray geometryArray = gi.getGeometryArray();
return new Shape3D(geometryArray);
}
private RotationInterpolator createRotation(final TransformGroup objScale, final Bounds bounds,
final Transform3D btrans, final long milis) {
final Alpha alpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, milis, 0, 0, 0, 0, 0);
final RotationInterpolator ri = new RotationInterpolator(alpha, objScale, btrans, 0.0f, (float) Math.PI * 2.0f);
ri.setSchedulingBounds(bounds);
return ri;
}
private void addLight(final BranchGroup group, final Color3f light1Color, final Vector3f ligthDirection) {
{
final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
final DirectionalLight light1 = new DirectionalLight(light1Color, ligthDirection);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
}
}
private void addLight(final BranchGroup group, final Color3f light1Color) {
{
final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
final AmbientLight light1 = new AmbientLight(light1Color);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
}
}
}
You will have to draw each face separately, assigning a color to each. For example:
Appearance polygon1Appearance = new Appearance();
// set your color here
QuadArray polygon1 = new QuadArray (4, QuadArray.COORDINATES);
polygon1.setCoordinate(0, new Point3f (0f, 0f, 0f));
polygon1.setCoordinate(1, new Point3f (2f, 0f, 0f));
polygon1.setCoordinate(2, new Point3f (2f, 3f, 0f));
polygon1.setCoordinate(3, new Point3f (0f, 3f, 0f));
objRoot.addChild(new Shape3D(polygon1, polygon1Appearance));
I'm having an issue with lighting. I'm using GLSL to achieve this. All seems fine however I'm having an issue I believe its called "banding". Essentially it's giving a gradient like effect to my lights. Perhaps I'm doing something wrong, here is my code that I'm using a long with an image of the problem. I'm a beginner in GLSL and not sure if the code I have is the most efficient way.
Main Code
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.glUseProgram;
import java.util.ArrayList;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
public class Main {
public final int width = 1280;
public final int height = 720;
public ArrayList<Light> lights = new ArrayList<Light>();
private Shader shader;
private int bufferIndex;
private float[] vertices;
private Light lighter;
private Vector2f lightPos;
private boolean lockedIn = false;
private void render() {
glClear(GL_COLOR_BUFFER_BIT);
for (Light light : lights) {
shader.bind();
shader.setUniformf("lightLocation", light.getLocation().x,
light.getLocation().y);
shader.setUniform("lightColor", new Vector3f(light.getColors()));
shader.setUniform("ambientLight", new Vector3f(0.1f, 0.1f, 0.1f));
shader.setUniform("baseColor", new Vector3f(0.2f, 0.2f, 0.2f));
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
VertexBufferObject.GetInstance().render();
glDisable(GL_BLEND);
glUseProgram(0);
}
Display.update();
Display.sync(60);
}
private void input() {
if (Input.getMouse(0))
lockedIn = true;
else if (Input.getMouse(1))
lockedIn = false;
if (lockedIn) {
Mouse.setGrabbed(true);
lightPos.set(Input.getMousePosition().x, Input.getMousePosition().y);
if (Input.getKey(Input.KEY_UP)) {
lighter.setBlue((float) (lighter.getBlue() + 1));
lighter.setRed(lighter.getRed() + 1);
lighter.setGreen(lighter.getGreen() + 1);
}
if (Input.getKey(Input.KEY_DOWN)) {
lighter.setBlue((float) (lighter.getBlue() - 1));
lighter.setRed(lighter.getRed() - 1);
lighter.setGreen(lighter.getGreen() - 1);
}
if (Input.getKey(Input.KEY_L)) {
lights.add(new Light(new Vector2f(Input.getMousePosition().x,
Input.getMousePosition().y), lighter.getRed(), lighter
.getGreen(), lighter.getBlue()));
lighter.setBlue((float) Math.random() * 10);
lighter.setGreen((float) Math.random() * 10);
lighter.setRed((float) Math.random() * 10);
}
} else {
Mouse.setGrabbed(false);
}
}
private void setUpObjects() {
lightPos = new Vector2f(50, 50);
lighter = new Light(lightPos, 0, 5, 10);
lights.add(lighter);
lights.add(new Light(new Vector2f(60, 60), 120, 0, 120));
}
private void initialize() {
try {
Display.setDisplayMode(new DisplayMode(width, height));
Display.setTitle("2D Lighting");
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
vertices = new float[] { 0, 0, 0, width, 0, 0, 0, height, 0, width,
height, 0, 0, height, 0, width, 0, 0 };
bufferIndex = glGenBuffers();
int b2 = glGenBuffers();
VertexBufferObject.GetInstance().addObject(bufferIndex, vertices);
VertexBufferObject.GetInstance().addObject(
b2, new float[] { 100, 100, 0, 200, 100, 0, 100, 200, 0, 200, 200,
0, 100, 200, 0, 200, 100, 0 });
VertexBufferObject.GetInstance().initObjects();
shader = new Shader();
shader.addFragmentShader(Shader.loadShader("shader.frag"));
shader.addVertexShader(Shader.loadShader("shader.vertex"));
shader.compileShader();
shader.addUniform("ambientLight");
shader.addUniform("baseColor");
shader.addUniform("lightLocation");
shader.addUniform("lightColor");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
}
private void cleanup() {
shader.unbind();
Display.destroy();
}
public static void main(String[] args) {
Main main = new Main();
main.setUpObjects();
main.initialize();
while (!Display.isCloseRequested()) {
if (Input.getKey(Input.KEY_ESCAPE))
System.exit(1);
main.input();
main.render();
}
main.cleanup();
}
}
GLSL Code
#verson 120
uniform vec2 lightLocation;
uniform vec3 lightColor;
uniform vec3 ambientLight;
uniform vec3 baseColor;
void main() {
vec4 light = vec4(ambientLight, 1);
vec4 color = vec4(baseColor,1);
float distance = length(lightLocation - gl_FragCoord.xy);
float attenuation = 1 / distance;
vec4 lColor = vec4(attenuation, attenuation, attenuation, pow(attenuation, 3)) * vec4(lightColor, 1);
color += lColor;
gl_FragColor = color * light;
}
Vertex Shader
#version 120
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
A result from the code:
I have adapted the code from Draw Text in OpenGL ES Android into my app, but the text isn't really showing up.
Here's what it currently looks like:
The green rectangle box is actually a Drawable bitmap.
I am expecting some sort of text, either white or black on top of the background, but nothing is ever showing up.
Here's the code for the Text class.
package gl.es;
import java.nio.*;
import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.Drawable;
import android.opengl.*;
import android.opengl.Matrix;
public class Text {
public int textTexture;
public FloatBuffer textFloatBuffer;
public FloatBuffer textureFloatBuffer;
public int bufferSize;
public int program;
private final int textWidth = 112;
private final int textHeight = 16;
//private float posX;
private int aTextPositionLocation;
private int aTexturePositionLocation;
private int uMatrixLocation;
private int uTextureUnitLocation;
public Text(Context context) {
program = Shader.buildProgram(context, R.raw.text_vert, R.raw.text_frag);
aTextPositionLocation = GLES20.glGetAttribLocation(program, "a_textPosition");
aTexturePositionLocation = GLES20.glGetAttribLocation(program, "a_texturePosition");
uMatrixLocation = GLES20.glGetUniformLocation(program, "u_matrix");
uTextureUnitLocation = GLES20.glGetUniformLocation(program, "u_textureUnit");
textTexture = createTexture(context);
setBuffer();
//posX = 0f;
}
public int createTexture(Context context) {
//Create empty mutable bitmap.
Bitmap bitmap = Bitmap.createBitmap(textWidth, textHeight, Bitmap.Config.ARGB_8888);
//Use Canvas to paint over it.
Canvas canvas = new Canvas(bitmap);
bitmap.eraseColor(0);
//Draw background
Drawable background = context.getResources().getDrawable(R.drawable.text_bg);
background.setBounds(0, 0, 112, 16);
background.draw(canvas);
//Draw text
Paint textPaint = new Paint();
textPaint.setTextSize(6f);
textPaint.setAntiAlias(false);
textPaint.setARGB(0xff, 0, 0, 0);
//Draw text centered.
canvas.drawText("Text.", 0, 0, textPaint);
int[] texture = new int[1];
GLES20.glGenTextures(1, texture, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
//Recycle.
bitmap.recycle();
return texture[0];
}
public void setBuffer() {
final float[] vertexData = {
0f, 0f,
textWidth, 0f,
0f, textHeight,
0f, textHeight,
textWidth, 0f,
textWidth, textHeight
};
final float[] texData = {
0f, 1f,
1f, 1f,
0f, 0f,
0f, 0f,
1f, 1f,
1f, 0f
};
textFloatBuffer = ByteBuffer.allocateDirect(vertexData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
textFloatBuffer.put(vertexData);
textureFloatBuffer = ByteBuffer.allocateDirect(texData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
textureFloatBuffer.put(texData);
bufferSize = vertexData.length / 2;
}
public void transform(float[] model, float[] projection, float[] mvp) {
Matrix.setIdentityM(model, 0);
Matrix.translateM(model, 0, 0f, 0f, -60f);
Matrix.translateM(model, 0, -60f, 0f, 0f);
Matrix.multiplyMM(mvp, 0, projection, 0, model, 0);
//posX = (posX - 0.3f) % 112f;
}
public void setVertexPointers() {
textFloatBuffer.position(0);
GLES20.glVertexAttribPointer(aTextPositionLocation, 2, GLES20.GL_FLOAT, false, 2 * 4, textFloatBuffer);
GLES20.glEnableVertexAttribArray(aTextPositionLocation);
textFloatBuffer.position(0);
textureFloatBuffer.position(0);
GLES20.glVertexAttribPointer(aTexturePositionLocation, 2, GLES20.GL_FLOAT, false, 2 * 4, textureFloatBuffer);
GLES20.glEnableVertexAttribArray(aTexturePositionLocation);
textureFloatBuffer.position(0);
}
public void draw() {
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, bufferSize);
}
public void useProgram() {
GLES20.glUseProgram(program);
}
public void setUniforms(float[] matrix) {
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textTexture);
GLES20.glUniform1i(uTextureUnitLocation, 1);
}
}
Could someone tell me where I'm doing wrong? What should I do in order to fix this? Thanks in advance.
UPDATE 1:
To answer deathember:
This is what happens when I changed the Matrix.transformM() to what you have suggested:
And here's the code that shows where I put my view matrix at:
package gl.es;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.*;
public class MyRenderer implements GLSurfaceView.Renderer
{
Context context;
Text text;
float eyeX;
float eyeY;
float eyeZ;
private float[] modelMatrix;
private float[] viewMatrix;
private float[] projectionMatrix;
private float[] modelViewProjectionMatrix;
public MyRenderer(Context context) {
this.context = context;
modelMatrix = new float[16];
projectionMatrix = new float[16];
viewMatrix = new float[16];
modelViewProjectionMatrix = new float[16];
}
#Override
public void onSurfaceCreated(GL10 p1, EGLConfig config)
{
// TODO: Implement this method
GLES20.glClearColor(0.4f, 0.8f, 1.0f, 1.0f);
this.text = new Text(this.context);
}
#Override
public void onSurfaceChanged(GL10 p1, int width, int height)
{
// TODO: Implement this method
GLES20.glViewport(0, 0, width, height);
this.setPerspectiveM(45f, (float) (width) / (float) (height), 1f, 200f);
// Did not use view matrix at all for transformations of Text textures.
Matrix.setLookAtM(viewMatrix, 0, 0, 0, 0, 0, 0, 0, 0, 1f, 0); //Unused.
Matrix.setIdentityM(modelMatrix, 0);
projectionMatrix, 0, modelMatrix, 0);
}
#Override
public void onDrawFrame(GL10 p1)
{
// TODO: Implement this method
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
text.transform(modelMatrix, projectionMatrix, modelViewProjectionMatrix);
text.useProgram();
text.setUniforms(modelViewProjectionMatrix);
text.setVertexPointers();
text.draw();
}
private void setPerspectiveM(float fov, float aspectRatio, float near, float far) {
final float anglesInRadians = (float) (fov * Math.PI / 180f);
final float angle = (float) (1f / Math.atan(anglesInRadians) / 2f);
projectionMatrix[0] = angle / aspectRatio;
projectionMatrix[1] = 0f;
projectionMatrix[2] = 0f;
projectionMatrix[3] = 0f;
projectionMatrix[4] = 0f;
projectionMatrix[5] = angle;
projectionMatrix[6] = 0f;
projectionMatrix[7] = 0f;
projectionMatrix[8] = 0f;
projectionMatrix[9] = 0f;
projectionMatrix[10] = -((far + near) / (far - near));
projectionMatrix[11] = -1f;
projectionMatrix[12] = 0f;
projectionMatrix[13] = 0f;
projectionMatrix[14] = -((2f * far * near) / (far - near));
projectionMatrix[15] = 0f;
}
}
Hope that helps.
Try to change
public void transform(float[] model, float[] projection, float[] mvp) {
Matrix.setIdentityM(model, 0);
Matrix.translateM(model, 0, 0f, 0f, -60f);
Matrix.translateM(model, 0, -60f, 0f, 0f);
Matrix.multiplyMM(mvp, 0, projection, 0, model, 0);
//posX = (posX - 0.3f) % 112f;
}
into
public void transform(float[] model, float[] projection, float[] mvp) {
Matrix.setIdentityM(model, 0);
Matrix.translateM(model, 0, 0f, 0f, 0f);
Matrix.multiplyMM(mvp, 0, projection, 0, model, 0);
//posX = (posX - 0.3f) % 112f;
}
And also set your view matrix look at center. May be you draw your text, but you can't see him. And where you set view matrix?
Add true inside view.getDrawingCache() as a parameter.
Note that on some devices and hardwares, this will never work. I found this out the hard way.
I have tried converting my LWJGL game to an applet but It can't load images, when I delete the code for the images it throws a null pointer exception, so Could SOmeone give me a walkthrough on how to Convert this code to an applet:
package com.kgt.platform.name;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import kuusisto.tinysound.Sound;
import kuusisto.tinysound.Music;
import kuusisto.tinysound.TinySound;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
import static org.lwjgl.opengl.GL11.*;
public class Game {
public static Player player;
public static Enemy enemy;
public static ExitButton exitbutton;
public static MenuButton menubutton;
public static ArrayList<Coin> coinlist;
public static ArrayList<Bullet> bulletlist;
public static ArrayList<Bullet2> bulletlist2;
public static ArrayList<Platform> platformlist;
public static ArrayList<OneWayPlatform> onewayplatformlist;
public static int score;
public static boolean p1on;
public static boolean p2on;
static State state = State.GAME;
public int curlvl = 1;
private static Texture logo;
private static Texture pause;
public enum State {
PAUSE, GAME, MAIN_MENU, INTRO;
}
public static void init() {
try {
// load texture from PNG file
logo = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/logo.png"));
System.out.println("Texture 'logo' Loaded. Format: PNG");
pause = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/paused.png"));
System.out.println("Texture 'pause' Loaded. Format: PNG");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void logo() {
Color.white.bind();
logo.bind(); // or GL11.glBind(texture.getTextureID());
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0);
GL11.glVertex2f(192,468);
GL11.glTexCoord2f(1,0);
GL11.glVertex2f(192+logo.getTextureWidth(),468);
GL11.glTexCoord2f(1,1);
GL11.glVertex2f(192+logo.getTextureWidth(),468- logo.getTextureHeight());
GL11.glTexCoord2f(0,1);
GL11.glVertex2f(192,468-logo.getTextureHeight());
GL11.glEnd();
}
public static void pause() {
Color.white.bind();
pause.bind(); // or GL11.glBind(texture.getTextureID());
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0);
GL11.glVertex2f(256,440);
GL11.glTexCoord2f(1,0);
GL11.glVertex2f(256+pause.getTextureWidth(),440);
GL11.glTexCoord2f(1,1);
GL11.glVertex2f(256+pause.getTextureWidth(),440- pause.getTextureHeight());
GL11.glTexCoord2f(0,1);
GL11.glVertex2f(256,440-pause.getTextureHeight());
GL11.glEnd();
}
public static void main(String[] args) throws Exception
{
System.setProperty("org.lwjgl.librarypath", new File("natives").getAbsolutePath());
System.out.println("Native Path: " + System.getProperty("org.lwjgl.librarypath"));
Display.setDisplayMode(new DisplayMode(640, 480));
Display.create();
init();
score = 0;
player = new Player();
exitbutton = new ExitButton(320, 61);
menubutton = new MenuButton(320, 95);
enemy = new Enemy();
coinlist = new ArrayList<Coin>(0);
bulletlist = new ArrayList<Bullet>(0);
bulletlist2 = new ArrayList<Bullet2>(0);
platformlist = new ArrayList<Platform>(0);
onewayplatformlist = new ArrayList<OneWayPlatform>(0);
Level1();
while(!Display.isCloseRequested())
{
setCamera();
drawBackground1();
for(Coin c: coinlist) c.draw();
for(Bullet b: bulletlist) b.draw();
for(Bullet2 b: bulletlist2) b.draw();
for(Platform b: platformlist) b.draw();
for(OneWayPlatform b: onewayplatformlist) b.draw();
enemy.draw();
player.draw();
states();
stateinput();
exitbutton.draw();
menubutton.draw();
Display.update();
Display.sync(60);
}
Display.destroy();
}
public static void stopsound(){
TinySound.shutdown();
}
public static void states(){
switch (state) {
case INTRO:
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(0, 0, 640, 480);
break;
case GAME:
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
break;
case MAIN_MENU:
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
glColor3f(0.0f, 0.0f, 1.0f);
glRectf(0, 0, 640, 480);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, logo.getTextureID());
logo();
break;
case PAUSE:
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
glEnable(GL_COLOR_ARRAY);
glBegin(GL_QUADS);
glColor4d(0.5f, 0.5f, 0.5, 0.7);
glVertex2d(224, 40);
glVertex2d(416, 40);
glColor4d(0.7f, 0.7f, 0.7, 0.7);
glVertex2d(416, 440);
glVertex2d(224, 440);
glEnd();
glDisable(GL_COLOR_ARRAY);
glColor3f(0f, 0f, 0f);
glRectf(224, 40, 226, 440);
glRectf(416, 40, 414, 440);
glRectf(224, 40, 416, 42);
glRectf(224, 438, 416, 440);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, pause.getTextureID());
pause();
break;
}
}
public static void stateinput(){
while (Keyboard.next()) {
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
if(state == State.GAME)
state = State.PAUSE;
else if(state == State.PAUSE)
state = State.GAME;
}
}
}
public static void jumpsound(){
TinySound.init();
Sound jump = TinySound.loadSound("/sound/Jump6.wav");
jump.play();
}
public static void shootsound(){
TinySound.init();
Sound shoot = TinySound.loadSound("/sound/Shoot1.wav");
shoot.play();
}
public static void selectsound(){
TinySound.init();
Sound select = TinySound.loadSound("/sound/select.wav");
select.play();
}
public static void hurtsound(){
TinySound.init();
Sound hurt = TinySound.loadSound("/sound/Hurt1.wav");
hurt.play();
}
public static void music(int track){
TinySound.init();
Music ocean = TinySound.loadMusic("/music/ocean.wav");
Music menu1 = TinySound.loadMusic("/music/menu1.wav");
if(track == 1){
ocean.play(true);
}
else if (track == 0){
menu1.play(true);
}
}
public static void setCamera(){
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL_COLOR_ARRAY);
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glEnable( GL11.GL_TEXTURE );
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glClearDepth(1);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glViewport(0,0,640,480);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 640, 0, 480, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
}
public static void Level1(){
Game.platformlist.add(new Platform(16, 120));
Game.platformlist.add(new Platform(48, 120));
Game.platformlist.add(new Platform(624, 120));
Game.platformlist.add(new Platform(592, 120));
Game.onewayplatformlist.add(new OneWayPlatform(128, 200));
Game.onewayplatformlist.add(new OneWayPlatform(160, 200));
music(1);
}
public static void drawBackground1(){
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
glBegin(GL_QUADS);
glColor3d(0.4, 0.5, 0.7);
glVertex2d(640, 480);
glVertex2d(0, 480);
glColor3d(0.7, 0.8, 0.9);
glVertex2d(0, 0);
glVertex2d(640, 0);
glEnd();
glBegin(GL_QUADS);
glColor3d(0.3, 0.2, 0.1);
glVertex2d(0, 0);
glVertex2d(640, 0);
glColor3d(0.5, 0.2, 0.1);
glVertex2d(640, 32);
glVertex2d(0, 32);
glEnd();
glBegin(GL_QUADS);
glColor3d(0.5, 0.2, 0.1);
glVertex2d(0, 32);
glVertex2d(640, 32);
glColor3d(0.2, 0.5, 0.1);
glVertex2d(640, 47);
glVertex2d(0, 47);
glColor3d(1, 1, 1);
glEnd();
}
}