I am using Google VR SDK to show an image on the screen.
I am encountering a strange bug when displaying the objects without distortion although it happens only on large screens (namely 5.5 inch or larger).
To disable distortion I am using gvrView.setDistortionCorrectionEnabled(false)
The result looks like this:
You can see that there is a cut part at the top of the screen that shows some of the objects again.
When I use distortion the problem seems to disappear.
I will give the relevant code here for reference:
public class MainActivity extends GvrActivity {
private GLSurfaceView mGLSurfaceView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fpv_activity_layout);
initGvrView();
}
private void initGvrView() {
GvrView gvrView = (GvrView) findViewById(R.id.gvr_view);
gvrView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
// Associate a GvrView.StereoRenderer with gvrView.
gvrView.setRenderer(new FpvRenderer(this));
AndroidCompat.setSustainedPerformanceMode(this, true);
gvrView.setDistortionCorrectionEnabled(false);
setGvrView(gvrView);
}
}
The XML file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.vr.sdk.base.GvrView
android:id="#+id/gvr_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
</RelativeLayout>
I am using this function to load the textures:
public static int loadTexture(final Context context, final int resourceId) {
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0) {
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
Has anyone encountered this, have any idea why this is happening and how to resolve it ?
I appreciate the help.
Related
I'm trying to change the texture image displayed on an object in my opengl view in response to a button click. Currently, when the user presses a button I set a flag to true in my OpenGL Renderer thread. My cross-thread communication seems fine: I am able to successfully toggle flag variables in the Renderer thread at will. My problem seems to be with the Open GL onDraw() workflow, I can't figure out how to systematically change a texture on an object after a texture has already been set during the Renderer's initial onSurfaceCreated() execution.
It seems that fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.dark_wood); never works outside of onSurfaceCreated(), why?
Below is the code i've tried. Am I missing a sequence of GLES20() method invocations somewhere?
OpenGL Renderer Class
private int chosenWoodColor = 1;
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
...
loadFretBoardTexture(); //this call works: it succeeds in changing texture
}
public void onDrawFrame(GL10 glUnused) {
if (flag){
loadFretBoardTexture(); //this call fails: it never changes the texture
}
...
//***Fretboard OpenGL_TextureData Binding***
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
// Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fretBoard._textureID);
//Draw Background
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -1.0f);
drawFretBoard(); //draw the fretboard
...
}
public void loadFretBoardTexture(){
switch (chosenWoodColor){
case 1:
fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.dark_wood);
break;
case 2:
fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.medium_wood);
break;
case 3:
fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.light_wood);
break;
}
setFretboardTextureRefresh(false);
return;
}
Texture Data Helper Class
public class OpenGL_TextureData {
public int textureID;
public float imageWidth, imageHeight;
public OpenGL_TextureData(Context context, int resourceId) { //constructor
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
//fetch texture image width & height
imageWidth = options.outWidth;
imageHeight = options.outHeight;
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0) {
throw new RuntimeException("Error loading texture.");
}
textureID = textureHandle[0];
}
}
Solved.
The problem was that I was creating a new texture object and loading a bitmap to it, but since the texture object was already created in my onSurfaceCreated() method this was undesired: I really just needed to load a bitmap onto the already existing texture object.
I added the following method to my Texture data helper class:
public void updateTexture(Context context, int resourceId) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options); //Read in the resource
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 1);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
Inspiration drawn from here
I will like to load textures during run time ( so I dont need to load all of the texture)
If I try to load a texture during run time with this function, I get the RunTimeException ( I think that is because the context is already created)
Is any way to do this without having 2 OpenlGL context(I read that this may cause error if the drivers are bad implemented)?
public static int loadTexture(final Context context, final int resourceId)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
I haven't touched OpenGL ES in Java, only C++ but I would have thought this would be perfectly OK - are you trying to create this texture on a different thread to the thread you created the OpenGL context on? Did your OpenGL context creation code succeed?
I am uploading loading images as textures to GLSurfaceView.
The resulting textures look perfectly fine on some devices, on others the appear completely distorted.
This is what it looks like on a Samsung Galaxy Nexus (screen density 2.0):
The same images on a Motorola (screen density 1.5):
Here is my loading code:
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
// Generate Texture
int[] texturenames = new int[1];
GLES20.glGenTextures(1, texturenames, 0);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
// Set wrapping mode
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
// Correct the bitmap if its not a power of two
Bitmap potTextureBitmap = textureBitmap;
int potWidth = nextPOT(textureBitmap.getWidth());
int potHeight = nextPOT(textureBitmap.getHeight());
if ((textureBitmap.getWidth() != potWidth) || (textureBitmap.getHeight() != potHeight)) {
potTextureBitmap = Bitmap.createScaledBitmap(textureBitmap, potWidth, potHeight, false);
}
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, potTextureBitmap, 0);
GLES20.glFlush();
return Integer.valueOf( texturenames[0]);
}
});
this.mSurfaceView.queueEvent(futureTask);
What am I doing wrong?
I finally found the cause of this problem.
Its rather specific, but I'll share the details anyhow:
There turned out to be an error in my color calculation. I need to convert from Hex colors to normalized rgba (in my case convert white #ffffffff to {1.0, 1.0, 1.0, 1.0}), but I actually fed non-normalized values into my shader (example: {255, 255, 255, 255}).
When multiplied with the color from my texture, the resulting colors would blow up.
Depending on the graphic card this caused the artifacts or not.
So the assumed dependency on the screen resolution was pure coincidence!
I'm trying to load multiple textures in my Applikation. The Problem is that the second texture isnt displayed right.
This is how i get the Handels:
mTextureDataHandle = TextureHelper.loadTexture(mActivityContext, R.drawable.full_texture);
mTextureDataHandleError = TextureHelper.loadTexture(mActivityContext, R.drawable.full_texture_error);
using this Method:
public static int loadTexture(final Context context, final int resourceId)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0 )
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
during the onDrawFrame method I use this to switch between Textures:
if (LessonFourActivity.error) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandleError);
GLES20.glUniform1i(mTextureUniformHandle, 1);
} else {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
GLES20.glUniform1i(mTextureUniformHandle, 0);
}
The texture without the error works fine but when i switch to the error texture it's just black.
Does anyone know an answer to this?
I already found a few answers regarding GL10 but they didnt help me.
I am building an android opengl es 2.0 application. I am drawing squares in a circle, and with the user's movements left and right I am moving the squares. I am applying textures on the squares and keep getting this error:
2-19 16:08:25.666: E/Adreno200-EGL(8183): eglLockWindowSurface: failed to map the memory
for fd=42 offs=6352896
I think that it has something to do with the textures. For loading the textures I use:
public static int loadTexture(final Context context, Bitmap bmp)
{
final int[] textureHandle = new int[1];
// GLES20.glDeleteTextures(1, textureHandle, 0);
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = bmp;
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
// bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
Note: with bitmap.recycle() the app does not work.
Also I must say that the onDraw() method is always working and the renderer is NOT set to RENDER_WHEN_DIRTY. I assume that I am loading too many textures and not doing anything to the old ones, but I can't solve this problem for several days now. If someone has a solution, please let me know. I will deeply appreciate any advice or feedback. Thank u in advance!!!