This issue is now fixed. My shader attributes were not bound correctly.
I have got a game, which when ran from the IDE looks like this:
However, when I export it from Eclipse with these settings,
The texturing is completely incorrect. The textures are still loaded, but they are not wrapping correctly onto the object.
The code is exactly the same, as I only just exported it, and I am currently running both windows of the game at the same time(One working fine from the IDE, one looking weird from an exported JAR).
I have also copied all the resources from the IDE directory to the folder with the external JAR. IDE directory:
Directory I run the external JAR from:
Also, I know that the textures are actually loading - They are not wrapping correctly. I know this because:
If you look at the plane, you can see that it still has elements of the texture - They are just all stretched and messed up.
Same thing with the Skybox. If you look at that, parts are still there, but again, it's incorrectly wrapped around the OBJ model.
If I hit the Q key to render the terrain with a DisplayList (Wrapping the terrain texture multiple times), it shows the texture. Can't get a screenshot of this because I can't hit Q and take a screenshot.
I have checked inside the JAR file, and the fragment and the vertex shader are still there. The correct libraries also appear to be there (Besides, if they weren't, the game would not even start).
Update:
As I was restarting the game multiple times to check for more information, I noticed that as soon as the display shows (so I can see the incorrectly-textured terrain and plane), the game freezes about 90% of the time. No Stacktrace, just a "This window is not responding and windows is closing it".
The game still works perfectly without crashing when I run it in the IDE.
The server for the game exports and runs perfectly. Only the client is the issue.
What about exporting could make the game any different than running it in the IDE, and how can I solve it?
Update:
So here is my texture loading code:
loader.loadTexture("PlaneTexture", 1);
//loadTexture() method:
public int loadTexture(String fileName, int mipmap) {
Texture texture = null;
try {
try{
texture = TextureLoader.getTexture("PNG", new FileInputStream("res/" + fileName + ".png")); //TextureLoader is a Slick-Util class.
}catch (Exception e){
e.printStackTrace();
}
if (texture == null){
throw new Exception("Null texture!");
}
//texture = TextureLoader.getTexture("GIF", new FileInputStream("res/" + fileName + ".png"));
if (mipmap > -10){
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, mipmap);
}
} catch (Exception e) {
e.printStackTrace();
System.err.println("Tried to load texture " + fileName + ".png , didn't work");
System.exit(1);
return -1;
}
textures.add(texture.getTextureID());
return texture.getTextureID();
}
I now have the texture ID of the texture. I then render the object (in this case the plane) like this:
Plane you = Main.TerrainDemo.shipsID.get(Main.TerrainDemo.UID);
Main.TerrainDemo.shader.start();
TexturedModel texturedModel = TerrainDemo.shipModel; //The plane model
RawModel model = texturedModel.getRawModel();
GL30.glBindVertexArray(model.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, TerrainDemo.shipModel.getTexture().getID()); //The ID of the texture.
glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
And, although I don't think they're important, my vertex and fragment shaders:
//Vertex shader
#version 130
in vec3 position;
in vec2 textureCoords;
in vec3 normal;
out vec2 pass_textureCoords;
out vec3 surfaceNormal;
out vec3 toLightVector;
uniform mat4 transformationMatrix;
uniform vec3 lightPosition;
void main(void){
gl_Position = ftransform();
pass_textureCoords = textureCoords;
surfaceNormal = (transformationMatrix * vec4(normal, 0.0)).xyz;
toLightVector = (vec3(500, 50000, 500)) - (transformationMatrix * vec4(position, 1.0)).xyz;
}
//Fragment shader
#version 130
in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector;
out vec4 out_Color;
uniform sampler2D textureSampler;
uniform vec3 lightColour;
void main(void){
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitLightVector = normalize(toLightVector);
float nDot1 = dot(unitNormal, unitLightVector);
float brightness = max(nDot1, 0.2);
brightness = brightness + 0.5;
vec3 diffuse = brightness * vec3(1, 1, 1);
vec4 textureColor = vec4(diffuse, 1.0) * texture(textureSampler, pass_textureCoords);
if(textureColor.a<1){
discard;
}
out_Color = vec4(textureColor.r, textureColor.g, textureColor.b, 1);
}
Again, I will stress that all of this is working perfectly if the game is running from the IDE. It is just if it runs from an external JAR that the issue occurs.
I will be experimenting with different texture loading techniques and methods (e.g. packing textures into the JAR) and seeing if anything different happens.
Yet another update:
So, I sent the game to another person (They also use windows 8), and the game worked perfectly! No texturing errors whatsoever! So now I'm unsure if the problem is with my PC specifically or something else.
For those who wish to try, you can download the game at http://endcraft.net/PlaneGame and see it yourself (Please read the instructions.txt - Also, you'll need a program to decompress .rar files).
I will be getting as many people as I know to give the game a go and see if they have the same issue or if the texturing is correct.
It is completely baffling me that it works fine when I run it from the IDE, but does not work when I export into an external jar, but does work when I export it into an external jar and send it to someone else!
(another) Update:
I have sent the game to multiple people, some of them are coming across this crash:
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x1cd6b57f, pid=36828, tid=35556
#
# JRE version: Java(TM) SE Runtime Environment (8.0_31-b13) (build 1.8.0_31-b13)
# Java VM: Java HotSpot(TM) Client VM (25.31-b07 mixed mode windows-x86 )
# Problematic frame:
# C [atioglxx.dll+0xc0b57f]
#
In the log file, I see this:
Stack: [0x011d0000,0x01220000], sp=0x0121f1e8, free space=316k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [atioglxx.dll+0xc0b57f]
C [atioglxx.dll+0xbe8b95]
C [atioglxx.dll+0x641852]
C [lwjgl.dll+0x9a28]
j org.lwjgl.opengl.GL20.glUniformMatrix4(IZLjava/nio/FloatBuffer;)V+33
j TMLoading.ShaderProgram.loadMatrix(ILorg/lwjgl/util/vector/Matrix4f;)V+23j
TMLoading.StaticShader.loadTransformationMatrix(Lorg/lwjgl/util/vector/Matrix4f;) V+6
j Joehot200.Plane.render()V+407
j Joehot200.TerrainDemo.render()V+4045
j Joehot200.TerrainDemo.enterGameLoop()V+356
j Joehot200.TerrainDemo.startGame()V+320
j StartScreenExperiments.Test2.resartTDemo()V+128
j StartScreenExperiments.Test2.main([Ljava/lang/String;)V+27
v ~StubRoutines::call_stub
V [jvm.dll+0x1473e5]
In other words, the entire issue (the texturing and the crashes) are beginning to look a lot like they are related to the shaders (either parsing information to them, or the actual shader code itself).
I have also done more testing, and the texturing works fine without shaders using a DisplayList.
Here is the code up to the glUniformMatrix() call:
//Some unnecessary code has been removed. For example, you do not care about what colour I make the plane depending on what team it is on.
//Plane class. (Referring to a jet plane which is the main object the player controls)
public void render(){
twodcoords = TextDemo.getScreenCoords(sx, sy + 30, sz);
glPushAttrib(GL_ENABLE_BIT);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glPushMatrix();
glTranslatef(sx, sy, sz);
GL30.glBindVertexArray(Main.TerrainDemo.vaoID);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glRotatef(srot, 0f, 1f, 0f);
glRotatef(pitch, -1f, 0f, 0f);
Main.TerrainDemo.shader.start();
glPushMatrix();
glDisable(GL_LIGHTING);
TexturedModel texturedModel = TerrainDemo.shipModel;
RawModel model = texturedModel.getRawModel();
GL30.glBindVertexArray(model.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, TerrainDemo.shipModel.getTexture().getID());
org.lwjgl.util.vector.Matrix4f m = Assist.createTransformationMatrix(new Vector3f(sx, sy, sz), new Vector3f(pitch, rot, roll), new Vector3f(5, 5, 5)); //Creates a transformation matrix based on the X, Y, Z, Pitch, yaw, roll, and scale of the plane.
Main.TerrainDemo.shader.loadTransformationMatrix(m);
glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL30.glBindVertexArray(0);
GL30.glBindVertexArray(0);
glPopMatrix();
glPopAttrib();
}
//StaticShader class. This method literally just passes it to the loadMatrix class.
public void loadTransformationMatrix(Matrix4f matrix){
super.loadMatrix(location_transformationMatrix, matrix);
}
//ShaderProgram class.
FloatBuffer buf = BufferUtils.createFloatBuffer(4 * 4);
public void loadMatrix(int location, Matrix4f matrix){
matrix.store(buf);
buf.flip();
GL20.glUniformMatrix4(location, false, buf);
}
Update - So, with one hour left on the Bounty, I thought I'd add a few more details:
As I probably said somewhere above, the game works for some when exported, but not for others. I've noticed that the game has always worked when ran on java 7, but with me only me and one other tester on java 7, this really isn't conclusive.
The texturing renders correctly in a DisplayList. The textures are loading. However, they are not being displayed correctly.
Even if you don't know the problem, trying out the game (ignore the start screen, I need to make a new one) and telling me the results, as well as your OS/Java details, etc, would be really appreciated.
Yes, the mipmapping is correct. I know someone in the comments mentioned it possibly wasn't, but I've tried setting it stupidly high and I do indeed get a very blurred texture.
I've already tried "package libraries into external jar". I appreciate the time taken for that answer, but I did say in the comments that I've already tried it.
The issue may be the fragment shader (as someone suggested in the comments), but I am currently unsure how to test it, nor do I understand why it would work inside the IDE but not outside of it.
I can't test this, so I'm not sure if this will help, but some implementations of OpenGL don't save element buffers in VAOs. So try binding the element buffer before the call to glDrawElements, e.g.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, someBuffer);
glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
If you don't do this, you may be using the last bound buffer for all draw calls. Probably not the answer, but it couldn't hurt to test it. I also noticed that you are using an older version of Slick, as you still have the slick-util, which is not part of the latest release, so you could also try updating that.
So try this instead of Extracting the required libraries try Package option instead, Because i personally believe there is an issue while finding those library files or linking some file then simply run the package.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 months ago.
Improve this question
I've been trying to learn glsl with OpenGL on IntelliJ and have been running into a few problems. First of my issues is with the #version.
#type vertex
#version 460
layout (location=0) in vec3 aPos;
layout (location=1) in vec4 aColor;
out vec4 fColor;
void main(){
fColor = aColor;
gl_Position = vec4(aPos, 1.0);
}
when I try to run this with my java in my java program I get an error message:
"ERROR: 0:1: '' : version '460' is not supported"\
Even though when I looked up my graphics chip (Intel Iris Graphics 550) it says it supports the openGL 4.60 API.
I put:
System.out.println(glGetString(GL_SHADING_LANGUAGE_VERSION));
which returns 1.20, and I'm not sure if I can get that to change to my needed 4.6 some how.
I believe that is also why I am receive my other error message which is:
"ERROR: 0:3: 'layout' : syntax error: syntax error"
I've tried a few things like having the extensions:
#extension GL_ARB_explicit_attribute_location : require
#extension GL_ARB_explicit_uniform_location : require
but then I just get "not supported" errors for those as well.
Any suggestions are appreciated!
If you need more info about the code I'm working on I've just been trying to follow a YouTube tutorial at
around 1:36:00-1:46:00
EDIT:
Here is where I initialized the OpenGL context:
//initialize GLFW
if(!glfwInit()){
throw new IllegalStateException("Unable to initialize GLFW.");
}
//configure GLFW
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
//create the window
glfwWindow = glfwCreateWindow(this.width, this.height, this.title, NULL, NULL);
if(glfwWindow == NULL) {
throw new IllegalStateException("Failed to create the window.");
}
glfwSetCursorPosCallback(glfwWindow, MouseListener::mousePosCallback);
glfwSetMouseButtonCallback(glfwWindow, MouseListener::mouseButtonCallback);
glfwSetScrollCallback(glfwWindow, MouseListener::mouseScrollCallback);
glfwSetKeyCallback(glfwWindow, KeyListener::keyCallback);
//make the OpenGl context current
glfwMakeContextCurrent(glfwWindow);
//Enable v-sync (buffer swapping)
glfwSwapInterval(1);
//Make window Visible
glfwShowWindow(glfwWindow);
GL.createCapabilities();
I got it to work by adding
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 3);
after my other window hints when I am initializing my context for my OpenGL window. then I changed the version in my .glsl file back to
#version 330 core
this also fixed my issue I had with the layout().
I am trying to copy image data provided by JCEF as a ByteBuffer to an OpenGL texture. When I pass the provided ByteBuffer to the glTexSubImage2D() call with the appropriate parameters the application crashes with EXCEPTION_ACCESS_VIOLATION (0xc0000005).
What I'm trying to do:
JCEF is a Java wrapper for CEF (Chromium Embedded Framework) and I am currently using the offscreen rendering model (as I want to render the browser in a 3d game using opengl).
JCEF provides updated screen data from the browser through an onPaint method with a list of dirty rectangles and a ByteBuffer with the updated screen data.
I want to copy that ByteBuffer onto an OpenGL Texture using glTexSubImage2D or similar.
I have confirmed that all values passed to the function call are valid and that the buffer provided to me by JCEF is long enough.
glGetError() calls after each OpenGL library call leading up to the crash return 0.
My opengl library is from LightWeight Java Game Library 3 (LWJGL3) and I have used it in all of my other code.
Searches on other threads and questions both here and on various other forums have all pointed to the ByteBuffer passed to OpenGL glTexSubImage2D() being too short. I have double and triple checked this and this is not the case. (As far as my understanding of OpenGL and its interpretation of data formats and types tell me.)
First some basic classes. This code is part of a Rendering Engine so I will only include what I feel is relevant but I am happy to attach more if needed.
The first class is a PreloadedTexture class. This represents a texture that has not come directly from a file but rather has been modified or generated in some way. It is my wrapper for an OpenGL Texture2D.
package com.base.shader;
import java.nio.ByteBuffer;
import static org.lwjgl.opengl.GL45.*;
public class PreloadedTexture {
int width;//The width of the texture in pixels
int height;//The height of the texture in pixels
int handle;//The OpenGL handle for the texture. This is used to reference this texture in other OpenGL calls
/*
This constructor creates a blank texture with the dimensions specified.
*/
public PreloadedTexture(int width, int height) {
super(Math.random() + "");
this.width = width;
this.height = height;
this.handle = glGenTextures();
glBindTexture(GL_TEXTURE_2D, handle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
}
/*EDIT: This method was renamed and had the internals changed to not bind the texture to a uniform sampler as mentioned in my comment below. It now just does a call to glBindTexture() as the uniform binding would occasionally return errors.
*/
public void bind(){
glBindTexture(GL_TEXTURE_2D, handle);
}
}
The BrowserWindow class is where most of the action happens but I have removed everything that isn't related to this problem.
package com.base.game;
import com.base.shader.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.awt.*;
import java.util.concurrent.LinkedTransferQueue;
import static org.lwjgl.opengl.GL46.*;
public class BrowserWindow {
private PreloadedTexture texture;//The texture that should be copied to.
private ByteBuffer imgData;//The BytBuffer provided by CEF with the updated screen data.
private LinkedTransferQueue<Rectangle> dirtyRects = new LinkedTransferQueue<>();//The list of dirty rects. The reasoning behind a LinkedTransferQueue is explained below.
int width;//The width of the browser view in pixels.
int height;//The height of the browser view in pixels.
/*
* Creates a browser window with the specified width and height. Initialises a ByteBuffer with image data to draw and a texture to draw to.
*/
public BrowserWindow(int _w, int _h){
width = _w;
height = _h;
imgData = ByteBuffer.allocate(width * height * 4 * Integer.BYTES);//This is later filled by the JCEF code but I have removed that as I know it works.
//The ByteBuffer is filled with bytes representing the screen data in BGRA format. Each Byte is a separate component of a pixel. The pixels are grouped together.
//This results in a structure like so: [B,G,R,A,B,G,R,A,etc.] I have maually checked that this data looks valid by going through portions of it and seeing understandable variances in the values.
texture = new PreloadedTexture(width, height); // An instance of the above PreloadedTexture class. The final destination for the imgData above.
}
//Called when the engine whats to render a frame. This should update the texture of the browser and then render the mesh with this texture. The actual mesh rendering code is ommited because again I know that works and it is not where the issue lies.
public void render(ShaderProgram shaderProgram, Camera camera) {
synchronized (imgData) {
//This block is to allow communication with the CEF thread.
//CEF runs the browser in a seperate thread and the onPaint method is called from there.
//OpenGL is not initialised in that thread however so I have used a LinkedTransferQueue<Rectangle> to transfer the dirty portions that need to be redrawn and the updated ByteBuffer is transferred byt directly setting it on the class.
//Again the actual code that does this has been ommitted as I know by checking the values manually that the data that is transfered is correct.
if (dirtyRects.size() > 0) {
//This just checks that there are dirty portions to update otherwise the call would waste both CPU and GPU time.
ArrayList<Rectangle> rects = new ArrayList<>();
//This provides a list to drop the Rectangles into for ease of access. These rectangles aren;t used at the moment but their implementation can be seen in the below commented out code.
dirtyRects.drainTo(rects);
imgData.rewind();
//This ensures that the imgData buffer is at the beggining.
texture.bind();
//Here I bind the texture to GL_TEXTURE_2D. The actual implementation is shown above in PreloadedTexture class.
System.out.println("Pre Render Error: " + glGetError());
//This checks to see if OpenGL was in an invalid state before and also clears the error buffer to ensure any errors reported from now on actually occur in this method.
System.out.println(glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) + ", " + glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT));
//This is a sanity check to ensure that the texture was initialised correctly in the PreloadedTexture constructor.
System.out.println(imgData.limit() + ", " + width * height * 4);
//This is another sanity check to ensure that the ByteBuffer is actually large enough. At the moment I have given it extra data to work with to see if it was the problem, hence the much larger limit of the ByteBuffer compared to the computed nescesary amount.
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
//These two calls reset the OpenGL state to ensure that rows and pixels aren't being skipped.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imgData);//This line results in the EXCEPTION_ACCESS_VIOLATION (0xc0000005)
System.out.println("Render Error: " + glGetError()); //This is a sanity check from before with another problem that I fixed.
//Below is the implementation that made use of the rectangles. It follows a similar pattern to the above code but only updates the specified rectangles.
// for (Rectangle rect : rects) {
// System.out.println(rect.x + ", " + rect.y + ", " + rect.width + ", " + rect.height);
// glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x);
// glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y);
// glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width, rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,imgData);
// }
}
imgData.notifyAll();//This notifies the CEF thread that the Rectangles and imgData objects are now free.
}
//Mesh rendering would happen here but again it has been omitted for conciseness this is not where the problem lies.
}
}
As I mentioned in the code comments I have double checked that the data from CEF is in a valid format. It follows a 4 byte repeating sequence of BGRA values. The ByteBuffer is plenty long enough as is shown by the sanity checks before the call to glTexSubImage2D();
Sorry for the amount of code but as I said earlier it is part of a rendering engine and much of the structure is influenced by that fact.
I expect the call to glTexSubImage2D() to copy the ByteBuffer data onto the OpenGL Texture2D however the call results in a EXCEPTION_ACCESS_VIOLATION (0xc0000005). The ByteBuffer is long enough and the data inside is in a valid format. I have also tried swapping GL_UNSIGNED_INT_8_8_8_8_REV with GL_UNSIGNED_INT_8_8_8_8 and GL_UNSIGNED_BYTE but they do not affect the outcome. When looking at the logs the exception occurs because it tried to access address 0x0000000000000010.
Does anyone know what might be causing this error. All my research has said that the ByteBuffer is too short, however, as I have said I have double checked this. Is my understanding of what is going on flawed or is this something else?
After some poking around in the error logs and looking at library sources I traced down the error to how I was allocating the ByteBuffer. The OpenGL library made use of a memory offset accessor (fairly obvious as to why), but the method of obtaining the offset expects the ByteBuffer to be direct. Changing the BrowserWindow class to instead use a direct buffer has fixed the error.
The updated portion is listed below for anyone else with a similar issue.
//This is the updated constructor from the BrowserWindow class
public BrowserWindow(int _w, int _h){
width = _w;
height = _h;
//imgData = ByteBuffer.allocate(width * height * 4 * Integer.BYTES); This is the old line that created a non-direct ByteBuffer.
imgData = ByteBuffer.allocateDirect(width * height * 4);//This is the new line. Note the allocateDirect() call and the removal of the extra space in the buffer in the form of Integer.BYTES.
texture = new PreloadedTexture(width, height);
}
What i'm trying to do:
Pull an image from sd-card on phone using Java Plugin.
Unity passes a texture ID to plugin.
Plugin uses opengl to assign the image to the texture in Unity through the ID.
Will (eventually) be used to play a video clip from the phone in Unity, for now, it's just trying to change a texture outside of unity.
My issue:
When i call the method in the plugin, passing texture.GetNativeTextureID() into it, the texture does not change. I'm currently only using a simple black 50x50 texture for testing, and the original texture is a flat white.
I'm worried that i've missed something significant, as this is my first time working with Gl calls in java. Much of the answers to similar problems involve using native C++ instead of Java, but I can't find a concrete answer saying that C++ must be used. I'd like to do my best to avoid writing another set of plugins and plugin handlers for C++, but if it's the most efficient/only way to get this working, i'll do it as i'm not unfamiliar with OpenGL and C++
Code:
The plugin method is called from OnPreRender() in a script attached to the main camera:
if (grabTex) {
int texPtr = m_VideoTex.GetNativeTextureID();
Debug.Log( "texPtr = " + texPtr );
m_JVInterface.SetTex( texPtr );
}
m_VideoTex is a basic Texture2D( 50, 50 ) with all pixels set to white, attached to the diffuse shader on the quad in the scene.
The Java plugin code is as follows:
public void SetTexture(Context cont, int _texPointer) {
if (_texPointer != 0) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inJustDecodeBounds = false;
final Bitmap bitmap = BitmapFactory.decodeFile("/storage/emulated/0/Pictures/black.jpg", options);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _texPointer);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
Log.i("VideoHandler", "Recieved ID: " + _texPointer);
bitmap.recycle();
}
}
This is most likely a problem with the OpenGL Context. The easiest way would be to send the texture as raw bytes to Unity and then upload as texture inside Unity.
I created a simple model of a barrel (.zip) in Blender 2.69. Then I created a UV map in Blender and made a UV mapped texture out of it (its in the archive, too). Then I imported my texture in Blender, now the mapping matches:
In Blender the model looks fine so far:
By using the Ogre exporter plugin that I installed via the jmonkeyengine SDK, I exported the model. The result of this is my OgreXML format file of the barrel (I did not export material).
Now, I tried to add the barrel to my world like this:
this.barrel = this.assetManager.loadModel("models/barrel/Barrel.mesh.xml");
Material barrelMat = new Material(this.assetManager,
"Common/MatDefs/Light/Lighting.j3md");
barrelMat.setTexture("DiffuseMap",
this.assetManager.loadTexture("models/barrel/Barrel.jpg"));
barrelMat.setBoolean("UseMaterialColors", true);
barrelMat.setColor("Diffuse", ColorRGBA.White);
barrelMat.setColor("Specular", new ColorRGBA(0.3f, 0.1f, 0, 1));
barrelMat.setFloat("Shininess", 4f);
this.barrel.setMaterial(barrelMat);
this.rootNode.attachChild(this.barrel);
The result is this:
Is there something else I have to consider when setting the texture for my UV mapped model?
Often when transferring models from Blender to something like JME, the textures will be upside down. Where you load the texture:
barrelMat.setTexture(“DiffuseMap”,
assetManager.loadTexture(“models/barrel/Barrel.jpg”));
Instead use the TextureKey form of the loadTexture() method and pass yFlip false since true is the default.
assetManager.loadTexture(new TextureKey(“models/barrel/Barrel.jpg”, false));
That should fix your issue.
References:
loadTexture() : http://hub.jmonkeyengine.org/javadoc/com/jme3/asset/AssetManager.html#loadTexture(com.jme3.asset.TextureKey)
TextureKey : http://hub.jmonkeyengine.org/javadoc/com/jme3/asset/TextureKey.html#TextureKey(java.lang.String,%20boolean)
I'm working on a simple 2D game engine in Java, and having no trouble with FSEM, buffer strategies, and so on; my issue is with the mouse cursor. In windowed mode, I can hide the mouse cursor, no problem, by using setCursor() from my JFrame to set a wholly-transparent cursor. However, after a call to device.setFullScreenWindow(this) to go into FSEM, the mouse cursor comes back, and subsequent calls to setCursor() to set it back to my blank cursor have no effect. Calling device.setFullScreenWindow(null) allows me to get rid of the cursor again - it's only while I'm in FSEM that I can't get rid of it.
I'm working under JDK 6, target platform is JDK 5+.
UPDATE: I've done some more testing, and it looks like this issue occurs under MacOS X 10.5 w/Java 6u7, but not under Windows XP SP3 with Java 6u7. So, it could possibly be a bug in the Mac version of the JVM.
Try Creating a custom invisible cursor:
Toolkit toolkit = Toolkit.getDefaultToolkit();
Point hotSpot = new Point(0,0);
BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TRANSLUCENT);
Cursor invisibleCursor = toolkit.createCustomCursor(cursorImage, hotSpot, "InvisibleCursor");
setCursor(invisibleCursor);
One developer found a way around it by creating a one pixel cursor out of a transparent GIF.
http://sevensoft.livejournal.com/23460.html
I know you tried that, but his is specifically addressing the issue of full-screen mode, exactly as you say, so perhaps there's something he's done that you haven't.
I think I've finally found the solution:
System.setProperty("apple.awt.fullscreenhidecursor","true");
This is an Apple-proprietary system property that hides the mouse cursor when an application is in full-screen mode. It's the only way I've found to fix it.
Here's what has been working for me:
Toolkit toolkit = Toolkit.getDefaultToolkit();
// get the smallest valid cursor size
Dimension dim = toolkit.getBestCursorSize(1, 1);
// create a new image of that size with an alpha channel
BufferedImage cursorImg = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
// get a Graphics2D object to draw to the image
Graphics2D g2d = cursorImg.createGraphics();
// set the background 'color' with 0 alpha and clear the image
g2d.setBackground(new Color(0.0f, 0.0f, 0.0f, 0.0f));
g2d.clearRect(0, 0, dim.width, dim.height);
// dispose the Graphics2D object
g2d.dispose();
// now create your cursor using that transparent image
hiddenCursor = toolkit.createCustomCursor(cursorImg, new Point(0,0), "hiddenCursor");
Granted, I haven't tested it on Mac (yet), only Windows. But when I used the common methods I was getting the cursor as black box, so I use the code above the create a transparent box and set it as the cursor instead. Of course you have to use the setCursor method on an AWT object (such as your app's Frame) to set this hiddenCursor. Here is my hideMouse method ('fr' is my Frame):
public void hideMouse(boolean hide) {
if(hide) {
fr.setCursor(hiddenCursor);
} else {
fr.setCursor(Cursor.getDefaultCursor());
}
}
I don't know if this knowledge applies but in a old VB6 app I had the same problem and I got rid of it moving the cursor out of the screen giving it some very large values.
Hope it helps.
If you're running only on Windows, it looks like you'll need to call ShowCursor(FALSE) through JNI. At least, to make the cursor hide complete.
Here's some code which creates the 1x1 cursor. It works for me, though I still get a 1x1 cursor.
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension dim = toolkit.getBestCursorSize(1,1);
transCursor = toolkit.createCustomCursor(gc.createCompatibleImage(dim.width, dim.height),
new Point(0, 0), "transCursor");
((Component)mainFrame).setCursor(transCursor);
Specifically for your Mac problem, through JNI you could use the following:
Quartz Display Services Reference - CGDisplayHideCursor