Jump to content

[1.11.2] [SOLVED] OpenGL Render problems


Bektor

Recommended Posts

Hi,

 

I've got a little problem with my OpenGL code while drawing a rectangular texture:

  • thousands of little textures will be drawn instead of one texture
  • the texture to display is part of a larger texture, but the wrong part of this huge "spritesheet" is drawn
  • those thousands of little textures are drawn on the wrong place of the screen

 

  • `guiStartX` and `guiStartY`: the x and y positions where the GUI should start
  • `textureX` and `textureY`: the position in the "spritesheet" where the texture can be found
  • `width` and `height`: the width and height of the texture to draw

 

 

mc.getTextureManager().bindTexture(UI_PROGRESS_TEXTURE);
int guiStartX = (mc.displayWidth - 16) / 2;
	int guiStartY = (mc.displayHeight - 51) / 2;
	renderTexturedRect(guiStartX, guiStartY, 176, 51, 16, 51);

renderTexturedRect(int x, int y, int textureX, int textureY, int width, int height) {
	glBegin(GL_QUADS);
	    glTexCoord2f(textureX, textureY);
	    glVertex3i(0, 0, 0);
	    
	    glTexCoord2f(textureX, textureY + height);
	    glVertex3i(0, height + 400, 0);
	    
	    glTexCoord2f(textureX + width, textureY + height);
	    glVertex3i(width + 800, height + 400, 0);
	    
	    glTexCoord2f(textureX + width, textureY);
	    glVertex3i(width + 800, 0, 0);
	    glEnd();

 

  1. One may ask, why not using drawTexturedModalRect from Minecraft itself. The Reason for this is that it is not available in the place where I am drawing.

  2. And why am I using OpenGL directly instead of for example looking into how drawTexturedModalRect renders a rectangle and doing it the same way?:

    The answer to this is that I am rather using OpenGL directly instead of using undocumented code where I do not even know what it is doing and how the stuff is getting onto the screen with using this (like where and which OpenGL calls are being called etc.)

 

Note: I am not familiar with OpenGL 2.1 nor with LWJGL 2 as I've only worked with OpenGL 4.5 (in C++) and it's shaders so far (and very little with LWJGL 3).

 

Thx in advance.

Bektor

Edited by Bektor

Developer of Primeval Forest.

Link to comment
Share on other sites

5 minutes ago, Bektor said:

One may ask, why not using drawTexturedModalRect from Minecraft itself. The Reason for this is that it is not available in the place where I am drawing.

Where are you doing this, then?

 

Also, you're not binding a texture.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

1 minute ago, Draco18s said:

Where are you doing this, then?

 

RenderGameOverlayEvent.Post calls a custom method which would then execute the code for specific blocks.

 

2 minutes ago, Draco18s said:

, you're not binding a texture.

I'm binding the texture directly above the first line of code I posted. ^^

Developer of Primeval Forest.

Link to comment
Share on other sites

1 hour ago, Bektor said:
  • thousands of little textures will be drawn instead of one texture
  • the texture to display is part of a larger texture, but the wrong part of this huge "spritesheet" is drawn

UVs must be within a range of [0-1] and you are passing a range of [0-16] x [0-51]. That won't work well. By default all MC textures have their wrap S/T set to repeat, and that's why you see "thousands of little textures" - it is actually your texture repeated 16 times on the x axis and 51 times on the y axis.

 

1 hour ago, Bektor said:

those thousands of little textures are drawn on the wrong place of the screen

Well, where are you expecting to see your quad? We can't tell what is wrong with the UI positioning just by looking at the code - although I can take a guess: you should subtract your position offsets after you've found the center of the screen.

 

1 hour ago, Bektor said:

One may ask, why not using drawTexturedModalRect from Minecraft itself. The Reason for this is that it is not available in the place where I am drawing.

There is absolutely nothing stopping you from using static methods in the GUI class. Or copying the method for that matter.

 

1 hour ago, Bektor said:

The answer to this is that I am rather using OpenGL directly instead of using undocumented code where I do not even know what it is doing and how the stuff is getting onto the screen with using this

I still suggest using BufferBuilder/VertexBuffer rather than OpenGL directly. There is a reason MC switched to it entirely. And well, some people might assume that all drawing is indeed done using methods from that class and abuse that.

Link to comment
Share on other sites

8 hours ago, V0idWa1k3r said:

Well, where are you expecting to see your quad? We can't tell what is wrong with the UI positioning just by looking at the code - although I can take a guess: you should subtract your position offsets after you've found the center of the screen.

 

Well, I want to place it in the middle of the screen.

8 hours ago, Abastro said:

Also, why don't use make use of x and y?

Well, I used them, thought it didn't went that good. Couldn't see the image anymore, so I started fixing the image first to get it properly drawn as one big image is easier to see then thousands of small images.

 

9 hours ago, V0idWa1k3r said:

I still suggest using BufferBuilder/VertexBuffer rather than OpenGL directly. There is a reason MC switched to it entirely. And well, some people might assume that all drawing is indeed done using methods from that class and abuse that.

I don't see any reason why BufferBuilder/VertexBuffer is the prefered way, especially when I do not know how it is connected to the hole rendering system and how those two classes work internally.

 

9 hours ago, V0idWa1k3r said:

UVs must be within a range of [0-1] and you are passing a range of [0-16] x [0-51]. That won't work well. By default all MC textures have their wrap S/T set to repeat, and that's why you see "thousands of little textures" - it is actually your texture repeated 16 times on the x axis and 51 times on the y axis.

 

Hm, now I am wondering, where does MC the conversion? I mean, when calling drawTexturedModalRect I don't think I ever passed the width of the complete image to draw, only the position and width and height of the part of the image to be drawn nor is the texture passed.

Developer of Primeval Forest.

Link to comment
Share on other sites

7 minutes ago, Bektor said:

Well, I want to place it in the middle of the screen.

Position it in the middle of the screen then. It would be screenWidth/2 - yourWidth/2, screenHeight/2 - yourHeight/2.

 

8 minutes ago, Bektor said:

I don't see any reason why BufferBuilder/VertexBuffer is the prefered way, especially when I do not know how it is connected to the hole rendering system and how those two classes work internally.

It is preferred because it is conventional. I mean in theory you can use java's ImageIO to load images from an InputStream, upload their pixel data to a buffer, setup a GLtexture and link the buffer to the texture every time you need a texture but you are not doing that, are you? Instead you use TextureManager::bindTexture. Same goes for BufferBuilder. And as I've said:

9 hours ago, V0idWa1k3r said:

And well, some people might assume that all drawing is indeed done using methods from that class and abuse that.

As to how it worksL it basically has an internal buffer it fills with data you pass to it. The offsets, strides and elements/vertex are controlled by the VertexFormat specified. Once you invoke draw the buffer is passed to OpenGL and rendered. It is somewhat of a complex yet very flexible wrapper around GL 3.0+ rendering. If you are familiar with GL4.5 you should be familiar with this aswell. As a side bonus it allows for "modern" shaders to be used(and MC does that in some cases).

 

15 minutes ago, Bektor said:

Hm, now I am wondering, where does MC the conversion? I mean, when calling drawTexturedModalRect I don't think I ever passed the width of the complete image to draw, only the position and width and height of the part of the image to be drawn nor is the texture passed.

Let's look at Gui::drawTexturedModalRect. Specifically at it signature:

public void drawTexturedModalRect(int x, int y, int textureX, int textureY, int width, int height)

The parameters I've marked as bold are to be processed into UVs in the method. textureX/Y are the start, and textureX/Y + width/height are the end. How are they processed? Well, let's look into that method. You will quickly notice that the results of manipulations with these values are multiplied by 0.00390625F. What is this magical number? It is 1/256. MC assumes the height/width of a GUI icon to be 256x256 and does calculations based on that assumption. If the texture is bigger in size(say via a resourcepack) it actually does not matter as the range of [0-1] is effectively a percentage and if the code is based around a 256x256 assumption(the variables passed to this method, that is) the end-result percentages are still going to be correct regardless of the texture width/height. 

 

Link to comment
Share on other sites

51 minutes ago, V0idWa1k3r said:

Let's look at Gui::drawTexturedModalRect. Specifically at it signature:

public void drawTexturedModalRect(int x, int y, int textureX, int textureY, int width, int height)

The parameters I've marked as bold are to be processed into UVs in the method. textureX/Y are the start, and textureX/Y + width/height are the end. How are they processed? Well, let's look into that method. You will quickly notice that the results of manipulations with these values are multiplied by 0.00390625F. What is this magical number? It is 1/256. MC assumes the height/width of a GUI icon to be 256x256 and does calculations based on that assumption. If the texture is bigger in size(say via a resourcepack) it actually does not matter as the range of [0-1] is effectively a percentage and if the code is based around a 256x256 assumption(the variables passed to this method, that is) the end-result percentages are still going to be correct regardless of the texture width/height. 

Changing my code to multiply the texture values with 1/256 just let's the complete image disappear.

        glTexCoord2f(textureX * (1/256), textureY * (1/256));
	    glVertex3i(0, 0, 0);
	    
	    glTexCoord2f(textureX * (1/256), (textureY + height) * (1/256));
	    glVertex3i(0, height + 400, 0);
	    
	    glTexCoord2f((textureX + width) * (1/256), (textureY + height) * (1/256));
	    glVertex3i(width + 800, height + 400, 0);
	    
	    glTexCoord2f((textureX + width) * (1/256), textureY * (1/256));
	    glVertex3i(width + 800, 0, 0);

 

51 minutes ago, V0idWa1k3r said:

It is somewhat of a complex yet very flexible wrapper around GL 3.0+ rendering.

Hm, why the hell creates Mojang wrappers around GL 3.0+ rendering instead of using it direclty. I mean, I don't know any graphics card today which doesn't support OpenGL 3.0+, even NVIDIAs GTX 400 series supports OpenGL 4.6 with the newest beta drivers and 4.5 with the newest stable drivers.

Developer of Primeval Forest.

Link to comment
Share on other sites

1 minute ago, Bektor said:

Changing my code to multiply the texture values with 1/256 just let's the complete image disappear.

Your textureX/Y are of an integer type. So is 1. And so is 256. Dividing an integer 1 by an integer 256 prouces you 0 and well, anything *0 is 0.

 

2 minutes ago, Bektor said:

Hm, why the hell creates Mojang wrappers around GL 3.0+ rendering instead of using it direclty.

Why do people create abstractions to begin with? Let's all write our code in assembly! That is sure going to be fun! :P

On a serious note - their BufferBuilder is very flexible - and that is why they did it. As long as you have the format you can easily upload anything you want to it and render it as desired without having to manualy setup GL buffers/arrays/attributes/younameit every time. Heck, you can even have custom formats defined and it will work just fine. Also it allows to easily modify the individual elements of the buffer if needed after they've been uploaded with a single method invocation. Doing it on a raw buffer is... A bit more challenging.

 

5 minutes ago, Bektor said:

don't know any graphics card today which doesn't support OpenGL 3.0+

And yet a lot of people had issues with MC starting to require OpenGL 3.3. I remember having one myself on a linux machine at work due to the way mesa drivers are done.

Link to comment
Share on other sites

17 minutes ago, V0idWa1k3r said:

Your textureX/Y are of an integer type. So is 1. And so is 256. Dividing an integer 1 by an integer 256 prouces you 0 and well, anything *0 is 0.

 

Always forget this one thing, but it didn't solve the problem. The texture is still gone:

	    glTexCoord2f(textureX * (1.f / 256.f), textureY * (1.f / 256.f));
	    glVertex3i(0, 0, 0);
	    
	    glTexCoord2f(textureX * (1.f / 256.f), (textureY + height) * (1.f / 256.f));
	    glVertex3i(0, height + 400, 0);
	    
	    glTexCoord2f((textureX + width) * (1.f / 256.f), (textureY + height) * (1.f / 256.f));
	    glVertex3i(width + 800, height + 400, 0);
	    
	    glTexCoord2f((textureX + width) * (1.f / 256.f), textureY * (1.f / 256.f));
	    glVertex3i(width + 800, 0, 0);

Hope I didn't forgot a small thing again, thought somehow I hope I did as it would solve the problem faster. ^^

 

17 minutes ago, V0idWa1k3r said:

Why do people create abstractions to begin with? Let's all write our code in assembly! That is sure going to be fun! :P

Assembly makes fun. You can even enforce a PC configuration with this as it won't run anywhere else. xD But why using Assembly, binary with its 01010101 is even better. :P 

 

17 minutes ago, V0idWa1k3r said:

And yet a lot of people had issues with MC starting to require OpenGL 3.3. I remember having one myself on a linux machine at work due to the way mesa drivers are done.

I don't know much about Mesa drivers, except that they got a somewhat stable OpenGL 4.5 support, but why not using official drivers?

And I don't think Minecraft uses OpenGL 3.3, the last version I know for sure they are using is OpenGL 2.1.

Edited by Bektor

Developer of Primeval Forest.

Link to comment
Share on other sites

35 minutes ago, Bektor said:

The texture is still gone:

Hm, interesting. Can you please elaborate on the word 'gone' in your scenario? I have debugged your code and had no issues with it - apart from the fact that it is rendered across the entire screen(I've got that fixed in my test) and the UVs point at a relatively small region of the image.

Spoiler

 

Here is my test sample:


@Override
public void invoke()
{
    Minecraft.getMinecraft().getTextureManager().bindTexture(new ResourceLocation("minecraft", "textures/gui/demo_background.png"));
    ScaledResolution sRes = new ScaledResolution(Minecraft.getMinecraft());
    int guiStartX = sRes.getScaledWidth() / 2 - 8;
    int guiStartY = sRes.getScaledHeight() / 2 - 26;
    this.renderTexturedRect(guiStartX, guiStartY, 176, 51, 16, 51);
}

void renderTexturedRect(int x, int y, int textureX, int textureY, int width, int height)
{
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2f(textureX * (1.f / 256.f), textureY * (1.f / 256.f));
    GL11.glVertex3i(x, y, 0);

    GL11.glTexCoord2f(textureX * (1.f / 256.f), (textureY + height) * (1.f / 256.f));
    GL11.glVertex3i(x, y + height, 0);

    GL11.glTexCoord2f((textureX + width) * (1.f / 256.f), (textureY + height) * (1.f / 256.f));
    GL11.glVertex3i(x + width, y + height, 0);

    GL11.glTexCoord2f((textureX + width) * (1.f / 256.f), textureY * (1.f / 256.f));
    GL11.glVertex3i(x + width, y, 0);
    GL11.glEnd();
}

 

 

 

 

Edited by V0idWa1k3r
Link to comment
Share on other sites

19 minutes ago, V0idWa1k3r said:

Hm, interesting. Can you please elaborate on the word 'gone' in your scenario? I have debugged your code and had no issues with it - apart from the fact that it is rendered across the entire screen and the UVs point at a relatively small region of the image.

 

Ok, fixed it with changing the first 51 parameter from my method to 0.

 

19 minutes ago, V0idWa1k3r said:

Here is my test sample:

Hm, I'm wondering what this invoke method is.

Edited by Bektor

Developer of Primeval Forest.

Link to comment
Share on other sites

8 minutes ago, Bektor said:

Even when implementing your ScaledResolution thing, it is still not drawn in the screen. Also when changing my glVertex3i to yours it is not drawn inside of the screen.

I suppose that would be because of these lines:

8 minutes ago, Bektor said:

int guiStartX = (sRes.getScaledWidth() - 16) / 2;

int guiStartY = (sRes.getScaledHeight() - 51) / 2;

 

8 minutes ago, Bektor said:

Hm, I'm wondering what this invoke method is.

A part of my testing framework that I use to debug code from people when I do not see an obvious issue.

 

8 minutes ago, Bektor said:

With gone I mean that it is nowhere to be seen on the screen as if it wouldn't be rendered at all, thought the code to render it is still be called.

Well, I am at a loss here then as this identical code works for me. If you don't mind could you please setup a github repo of your project(or a minimal part of it that allows the issue to be reproduced reliably) that can be cloned and debugged locally. I could then debug it with your exact conditions to try to figure out what exactly is wrong.

EDIT: even though you've fixed it I am still curious as to what the issue was exactly. Was it a texture issue? 

Edited by V0idWa1k3r
Link to comment
Share on other sites

3 minutes ago, V0idWa1k3r said:
11 minutes ago, Bektor said:

int guiStartX = (sRes.getScaledWidth() - 16) / 2;

int guiStartY = (sRes.getScaledHeight() - 51) / 2;

 

Fixed with changing the first 51 parameter from my method to 0. The ScaledResolution thing also solved problems with disappering textures when changing the screen size, which I didn't even noticed before. :) 

 

3 minutes ago, V0idWa1k3r said:

EDIT: even though you've fixed it I am still curious as to what the issue was exactly. Was it a texture issue? 

I suppose it was an issue with missing ScaledResolution and me having the reading direction for OpenGL texture coordinates wrong in my head.

Edited by Bektor

Developer of Primeval Forest.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.