Hello Guest

Physically-Based Rendering for LWJGL?

  • 3 Replies
Physically-Based Rendering for LWJGL?
« on: November 30, 2017, 07:12:52 »
Hello there. I've been working with LWJGL for the past couple of months by following several tutorials, some on youtube and some elsewhere. I've managed to build a program with some relatively simple phong lighting with texturing so on and so on.

I've been learning about Physically based rendering from a learnopengl.com tutorial which has a really interesting tutorial on the topic with code in C++. I've been trying to port the code over as a means of understanding the binding of uniforms with the shader. While it all seems relatively understanble, I can't seem to figure out the bindings of the uniforms, and how to upload information to the shaders uniform. It seems really confusing, and it might mean I'll have to start from scratch in c++ with glm. Anyone have info or advice to learning physically based rendering? If you'd like to look at my source code in LWJGL2, I'll update this in a moment so I can put out some code trouble I'm having.



Re: Physically-Based Rendering for LWJGL?
« Reply #1 on: December 06, 2017, 13:43:46 »
c++ nor glm are not going to help your understanding of uniforms, you link to learnopengl and that is a  good resource. The conversion to java is very simple. If you want to get help post some code of how you are attempting to do things and then people can provide feedback.

my advice is to do the following

- define a set of uniforms you want and add them to all the shaders you need them in. if you want to share uniforms across shaders then make sure the declaration is identical in each.
- if you use an advanced enough opengl set the binding location number of the uniforms in the shader (using binding=7 as an example)
- if you don't, when you create and register your shader go through all your uniforms and get their index using the uniform name. Then map this index to the binding location of your choice. But make sure you use the same location for a particular across all shaders.
- with this binding location number you can then update the data for all your shaders to access in one call per uniform.

Re: Physically-Based Rendering for LWJGL?
« Reply #2 on: December 11, 2017, 04:51:13 »
Hey! Thanks for responding. I've decided to have another go and have made little success. I have the location of the projection, view and model set up using the Thinmatrix code along with the functions from that tutorial. The matrices are assigned in its own function, like loadTransformationMatrix, loadProjectionMatrix etc. The staticShader class that sends data to the uniforms is extended by the shaderProgram class, which holds functions such as loadFloat and loadVector, which does all the uploading to the uniforms in the shader. The vert and frag shaders seem to be registering. I have a location_albedo setup to read the albedo from the fragment shader, and I made a new function called loadPBR() which holds the super.loadVector("location_albedo" new Vector3f(10,2,0)); I can change the color of the sphere from this function but with no lighting, and nothing is registering the normals(?) This seems to work except there is no lighting been applied, and the previous lighting was setup in a loop like so:

for(int i=0;i<MAX_LIGHTS;i++) {
   location_lightPosition = super.getUniformLocation("lightPositions[" + i + "]");
   location_lightColour = super.getUniformLocation("lightColors[" + i + "]");

I'm unsure how I'm supposed to send data to the uniforms through a loop. The uniforms are a vec3, so I supposed I could use a loop and have the super.loadVector(location_lightPosition)... inside the loop similar to the one above.

Inside the loadPBR function I have also setup:

   super.loadVector(location_albedo, new Vector3f(1,3,20));
   super.loadFloat(location_metallic, 0.3f);
   super.loadFloat(location_roughness, 0.4f);
   super.loadFloat(location_ao, 0.4f);

The function is setup in the staticShader class and is initialized in the renderer class. I'm unsure if this is the right place to initialize the loadPBR function.

This is the code in the staticShader class, I've currently got these assigned.

   protected void bindAttributes() {
      //bind attributes ex super.bindAttribute(0, "position");

      //super.bindAttribute(0, "position");
      //super.bindAttribute(1, "textureCoordinates");

      super.bindAttribute(0, "aPos");
      super.bindAttribute(1, "aTexCoords");
      super.bindAttribute(2, "aNormal");


   protected void getAllUniformLocations() {
      // uniform locations ex. location_transformationMatrix = super.getUniformLocation("transformationMatrix");

      //location_transformationMatrix = super.getUniformLocation("model");
      location_model = super.getUniformLocation("model");
      location_projectionMatrix = super.getUniformLocation("projection");
      location_viewMatrix = super.getUniformLocation("view");
      location_camPos = super.getUniformLocation("camPos");

      location_albedo = super.getUniformLocation("albedo");
      location_metallic = super.getUniformLocation("metallic");
      location_roughness = super.getUniformLocation("roughness");
      location_ao = super.getUniformLocation("ao");
      for(int i=0;i<MAX_LIGHTS;i++) {
         location_lightPosition = super.getUniformLocation("lightPositions[" + i + "]");
         location_lightColour = super.getUniformLocation("lightColors[" + i + "]");

the camPos is currently doing nothing, which means I might have to revise over the learnOpengl website as to how the camPos is being applied.

Heres a link to the full code I'm working on.


My apologies if the code is a bit bloated. Any help would be much appreciated. Thanks!

« Last Edit: December 11, 2017, 04:53:45 by wini »

Re: Physically-Based Rendering for LWJGL?
« Reply #3 on: December 11, 2017, 12:11:37 »

So I managed to get the first part of the tutorial going.

Now I'm trying to apply the the texture data to the Sampler2D for each texture map(albedo, roughness, metallic, ao). I have a TexturedModel class that can take
TexturedModel staticModel = new TexturedModel(model,albedo, roughness, metallic, ao);
like so. But I'm unsure how its meant to connect.

I decided to revise on the linking of textures through a thinmatrix video. So far I came up with this.

in the renderer class:
      //Activate texture albedo texture 0
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getAlbedo().getID());

      //Activate texture roughness texture 1
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getRoughness().getID());

      //Activate texture metallic texture 2
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getMetallic().getID());

      //Activate texture ao texture 0
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getAo().getID());

I can't change the albedo, roughness, metallic and ambient occlusion as I did before, they're all set based on the maps. The albedo seems to work, but appears very dark. I found a pbr texture set with the albedo, roughness and ao map. It also had a height and normal map, which I assume can be applied as well if I set myself up towards a normal mapping tutorial (which I have done through previous tutorials but without the new lighting.As for the roughness and ao map, I can't tell if its working. So far it looks like this:

Heres where I got to previously. I assigned some keys and manipulated the lighting to a desired effect.

I still don't understand how I can utilize multiple lights. Thinmatrix has a tutorial that deals with that so I may just revisit it and try to understand it a better. If anyone has any clues that can lead me into the right direction I'd very much appreciate it.

pbr shader test without texture https://github.com/winnieTheWind/PBRTest-AlbedoRoughnessMetallicAO

pbr shader test with texture maps https://github.com/winnieTheWind/PBRTest-AlbedoRoughnessMetallicAOMaps


« Last Edit: December 11, 2017, 12:19:14 by wini »