Specular/Normalmap with custom renderer

WorldRenderEvents.BEFORE_ENTITIES.register(context -> {
MinecraftClient mc = MinecraftClient.getInstance();
RenderLayer renderLayer = NewRenderLayer.getNewLayer(new Identifier("luminance", "textures/re45.png"));
VertexConsumerProvider.Immediate immediate = mc.getBufferBuilders().getEntityVertexConsumers();
VertexConsumer vertexConsumer = immediate.getBuffer(renderLayer);

context.matrixStack().push();
context.matrixStack().translate(-context.camera().getPos().x, -context.camera().getPos().y, -context.camera().getPos().z);

if(!modelBuffers.containsKey("myModel"))
bakeModel("myModel", objParser);

// render via baked buffer
VertexBuffer vertexBuffer = modelBuffers.get("myModel");

renderLayer.startDrawing();
vertexBuffer.bind();

// temp fix: lighting is baked, so I artificially darken the whole model (to be implemented)
RenderSystem.setShaderColor(0.0f, 0.0f, 0.0f, 1.0f);

Matrix4f m4f = new Matrix4f(context.matrixStack().peek().getPositionMatrix());
var matrix = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(m4f);
vertexBuffer.draw(matrix, context.projectionMatrix(), GameRenderer.getRenderTypeEntitySolidProgram());

renderLayer.endDrawing();
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);

context.matrixStack().pop();
});
WorldRenderEvents.BEFORE_ENTITIES.register(context -> {
MinecraftClient mc = MinecraftClient.getInstance();
RenderLayer renderLayer = NewRenderLayer.getNewLayer(new Identifier("luminance", "textures/re45.png"));
VertexConsumerProvider.Immediate immediate = mc.getBufferBuilders().getEntityVertexConsumers();
VertexConsumer vertexConsumer = immediate.getBuffer(renderLayer);

context.matrixStack().push();
context.matrixStack().translate(-context.camera().getPos().x, -context.camera().getPos().y, -context.camera().getPos().z);

if(!modelBuffers.containsKey("myModel"))
bakeModel("myModel", objParser);

// render via baked buffer
VertexBuffer vertexBuffer = modelBuffers.get("myModel");

renderLayer.startDrawing();
vertexBuffer.bind();

// temp fix: lighting is baked, so I artificially darken the whole model (to be implemented)
RenderSystem.setShaderColor(0.0f, 0.0f, 0.0f, 1.0f);

Matrix4f m4f = new Matrix4f(context.matrixStack().peek().getPositionMatrix());
var matrix = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(m4f);
vertexBuffer.draw(matrix, context.projectionMatrix(), GameRenderer.getRenderTypeEntitySolidProgram());

renderLayer.endDrawing();
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);

context.matrixStack().pop();
});
Hey, I wanted to ask something! This is my custom code for rendering OBJ meshes which works, with rethinking voxels it also recieves shadows, AO etc. I wanted to ask, is it possible to also bind the specular and normal maps? Can the shader work with that and use it (for example for screen space reflections and normal maps)? :)
No description
560 Replies
Sinan
SinanOP17mo ago
@IMS Hello, given your bio I thought I might ping you for this :) Is it possible to bind the specular and normal maps alongside my rendering, aka do the shaderpack shaders have access to that?
IMS
IMS16mo ago
sorry, didn't get to this
Sinan
SinanOP16mo ago
No problem, thank you for answering
IMS
IMS16mo ago
The way this is supposed to work is you use AbstractTexture's, and then you can just have _s and _n variants of those textures and Iris should just know how to use them
Sinan
SinanOP16mo ago
May I ask in which sense? In my code above I do not render like normal blocks or items
IMS
IMS16mo ago
so first try adding textures/re45_s.png any sense, it's caught at texture binding not at blocks or entities
Sinan
SinanOP16mo ago
Yes, I have the _s and _n with new Identifier Oh okay, I never heard about AbstractTextures, I am scrolling through the docs but I am unsure on how to use them Nvm! So basically:
AbstractTexture texture_s = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("luminance", "textures/re45_s.png"));

AbstractTexture texture_n = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("luminance", "textures/re45_n.png"));
RenderSystem.activeTexture(GlConst.GL_TEXTURE1);
RenderSystem.bindTexture(texture_s.getGlId());
RenderSystem.activeTexture(GlConst.GL_TEXTURE2);
RenderSystem.bindTexture(texture_n.getGlId());
AbstractTexture texture_s = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("luminance", "textures/re45_s.png"));

AbstractTexture texture_n = MinecraftClient.getInstance().getTextureManager().getTexture(new Identifier("luminance", "textures/re45_n.png"));
RenderSystem.activeTexture(GlConst.GL_TEXTURE1);
RenderSystem.bindTexture(texture_s.getGlId());
RenderSystem.activeTexture(GlConst.GL_TEXTURE2);
RenderSystem.bindTexture(texture_n.getGlId());
I should do this before calling draw?
IMS
IMS16mo ago
no don't do anything with _s or _n pretend they don't exist, just have them Iris will grab them for you if you're registering them, also don't do that
Sinan
SinanOP16mo ago
Oh uhm, I should just have them as files?
IMS
IMS16mo ago
yep
Sinan
SinanOP16mo ago
Woah I'm gonna give it a shot Hmm that did not seem to work, I will provide you with my code:
Sinan
SinanOP16mo ago
First off I think this is what you meant?
No description
IMS
IMS16mo ago
yep
Sinan
SinanOP16mo ago
This is my render code:
WorldRendererEvents.BEFORE_ENTITY.register(context -> {
Vec3d pos = new Vec3d(0,0,0);
int blockLight = context.world().getLightLevel(LightType.BLOCK, new BlockPos((int)pos.x, (int)pos.y, (int)pos.z));
int skyLight = context.world().getLightLevel(LightType.SKY, new BlockPos((int)pos.x, (int)pos.y, (int)pos.z));
int packedLight = packLight(blockLight, skyLight);

MinecraftClient mc = MinecraftClient.getInstance();
RenderLayer renderLayer = NewRenderLayer.getNewLayer(new Identifier("luminance", "textures/re45.png"));
VertexConsumerProvider.Immediate immediate = mc.getBufferBuilders().getEntityVertexConsumers();
VertexConsumer vertexConsumer = immediate.getBuffer(renderLayer);

context.matrixStack().push();
context.matrixStack().translate(-context.camera().getPos().x, -context.camera().getPos().y, -context.camera().getPos().z);

if(!modelBuffers.containsKey("myModel"))
bakeModel("myModel", objParser);


int newBlockLight = Math.min(roundToNearestArray(blockLight, blockLightSteps), 15);
int newSkyLight = Math.min(roundToNearestArray(skyLight, skyLightSteps), 15);
int newLight = packLight(newBlockLight, newSkyLight);


VertexBuffer vertexBuffer = modelBuffers.get("myModel").get(newLight);

if(vertexBuffer != null) {
renderLayer.startDrawing();
vertexBuffer.bind();

shaderLights[0] = ShaderLights.lastShaderLights[0];
shaderLights[1] = ShaderLights.lastShaderLights[1];

context.matrixStack().push();
context.matrixStack().multiply(new Quaternionf().rotateYXZ(45,0,0));
context.matrixStack().scale(3,3,3);
context.matrixStack().translate(2,0,0);

RenderSystem.setShaderLights(shaderLights[0], shaderLights[1]);
Matrix4f m4f = new Matrix4f(context.matrixStack().peek().getPositionMatrix());
var matrix = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(m4f);


vertexBuffer.draw(matrix, context.projectionMatrix(), GameRenderer.getRenderTypeEntitySolidProgram());

renderLayer.endDrawing();
context.matrixStack().pop();
}

context.matrixStack().pop();
});
WorldRendererEvents.BEFORE_ENTITY.register(context -> {
Vec3d pos = new Vec3d(0,0,0);
int blockLight = context.world().getLightLevel(LightType.BLOCK, new BlockPos((int)pos.x, (int)pos.y, (int)pos.z));
int skyLight = context.world().getLightLevel(LightType.SKY, new BlockPos((int)pos.x, (int)pos.y, (int)pos.z));
int packedLight = packLight(blockLight, skyLight);

MinecraftClient mc = MinecraftClient.getInstance();
RenderLayer renderLayer = NewRenderLayer.getNewLayer(new Identifier("luminance", "textures/re45.png"));
VertexConsumerProvider.Immediate immediate = mc.getBufferBuilders().getEntityVertexConsumers();
VertexConsumer vertexConsumer = immediate.getBuffer(renderLayer);

context.matrixStack().push();
context.matrixStack().translate(-context.camera().getPos().x, -context.camera().getPos().y, -context.camera().getPos().z);

if(!modelBuffers.containsKey("myModel"))
bakeModel("myModel", objParser);


int newBlockLight = Math.min(roundToNearestArray(blockLight, blockLightSteps), 15);
int newSkyLight = Math.min(roundToNearestArray(skyLight, skyLightSteps), 15);
int newLight = packLight(newBlockLight, newSkyLight);


VertexBuffer vertexBuffer = modelBuffers.get("myModel").get(newLight);

if(vertexBuffer != null) {
renderLayer.startDrawing();
vertexBuffer.bind();

shaderLights[0] = ShaderLights.lastShaderLights[0];
shaderLights[1] = ShaderLights.lastShaderLights[1];

context.matrixStack().push();
context.matrixStack().multiply(new Quaternionf().rotateYXZ(45,0,0));
context.matrixStack().scale(3,3,3);
context.matrixStack().translate(2,0,0);

RenderSystem.setShaderLights(shaderLights[0], shaderLights[1]);
Matrix4f m4f = new Matrix4f(context.matrixStack().peek().getPositionMatrix());
var matrix = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(m4f);


vertexBuffer.draw(matrix, context.projectionMatrix(), GameRenderer.getRenderTypeEntitySolidProgram());

renderLayer.endDrawing();
context.matrixStack().pop();
}

context.matrixStack().pop();
});
This is all I do basically
IMS
IMS16mo ago
what is NewRenderLayer.getNewLayer?
Sinan
SinanOP16mo ago
And this is the renderlayer:
public static RenderLayer getNewLayer(Identifier texture) {
return NewRenderLayer.of("newlasl", VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, VertexFormat.DrawMode.TRIANGLES, 256, false, false, MultiPhaseParameters.builder().program(ENTITY_SOLID_PROGRAM).texture(new RenderPhase.Texture((Identifier)texture, false, false)).transparency(RenderPhase.NO_TRANSPARENCY).lightmap(ENABLE_LIGHTMAP).build(false));
}
public static RenderLayer getNewLayer(Identifier texture) {
return NewRenderLayer.of("newlasl", VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, VertexFormat.DrawMode.TRIANGLES, 256, false, false, MultiPhaseParameters.builder().program(ENTITY_SOLID_PROGRAM).texture(new RenderPhase.Texture((Identifier)texture, false, false)).transparency(RenderPhase.NO_TRANSPARENCY).lightmap(ENABLE_LIGHTMAP).build(false));
}
IMS
IMS16mo ago
hm, ok that should be making a simpletexture... just to be sure; you're using a shader that actually uses pbr and you've tested it with packs?
Sinan
SinanOP16mo ago
Yes, I am using rethinking voxels and no, I have not tested it with packs actually
IMS
IMS16mo ago
i don't believe rethinking voxels has pbr? try it's non-voxel version, Complementary reimagined
Sinan
SinanOP16mo ago
Omg now that you say it I had to switch PBR support to SEUSPBR Omg I think its working HOW BEAUTIFUL I just need to convert the yellow normalmap to the purple standard and I can show it here
IMS
IMS16mo ago
👍 yeah, try moving to labPBR if you can
Sinan
SinanOP16mo ago
Alright! Oh yes, I just read labPBR even has dielectric/metal support :o
IMS
IMS16mo ago
yeah, quick note about that some shaders support that, some don't for example reimagined/rethinking voxels don't last I checked?
Sinan
SinanOP16mo ago
Oh okay! Still, that's so freaking awesome that Iris automatically loads that! I LOVE IRIS
IMS
IMS16mo ago
no problem!
Sinan
SinanOP16mo ago
Hm, when I change from Integrated PBR+ to SEUSPBR or labsPBR, the whole lighting changes drastically. However, I really liked the Integrated PBR look...
Sinan
SinanOP16mo ago
Integrated
No description
IMS
IMS16mo ago
Integrated PBR does not allow any PBR textures
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
SEUSPBR/labPBR
IMS
IMS16mo ago
it's PBR hardcoded to the shader that doesn't look right... what pack is it? oh wait you're on rethinking voxels yeah seuspbr is broken there
Sinan
SinanOP16mo ago
Ah okay I see... Is there a way to get the hardcoded properties to a resourcepack?
IMS
IMS16mo ago
try Complementary Reimagined
Sinan
SinanOP16mo ago
Yes
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
But this is labPBR :( I really love rethinking voxels and would super like to stick with it
IMS
IMS16mo ago
it's a bug in rethinking voxels
Sinan
SinanOP16mo ago
I will however try the other pack too
IMS
IMS16mo ago
Rethinking Voxels is an edit of this other pack this is the original
Sinan
SinanOP16mo ago
But without voxelization or how can I understand that?
IMS
IMS16mo ago
it's without the ray traced shadows and lights, yeah same look though
Sinan
SinanOP16mo ago
Ah that's unfortunate, I really fell in love with RV for exactly that
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Okay, this is complementary with seuspbr and labpbr, looks the same, I guess because now it is relying on the non existent maps right?
IMS
IMS16mo ago
yep, now add this
Sinan
SinanOP16mo ago
May I ask is there a way to get the hardcoded properties into a resource pack?
IMS
IMS16mo ago
yes, one second well partially
Sinan
SinanOP16mo ago
Ah thanks!
Sinan
SinanOP16mo ago
Hm, this does not look right
No description
Sinan
SinanOP16mo ago
specular map is set to completely white and the normalmap looks like this:
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
specular map should be black white means you want everything hyper bright
Sinan
SinanOP16mo ago
I wanted to see highly reflective
IMS
IMS16mo ago
then you need to properly change that iirc
Sinan
SinanOP16mo ago
I will now build the maps according to labPBR standard, brb
IMS
IMS16mo ago
add this texture pack to your game
IMS
IMS16mo ago
it's Vanilla Normals Renewed, a pack that recreates that same look iPBR gives to some extent
Sinan
SinanOP16mo ago
Thank you! Regarding the RV bug, do you know what is happening there? And is it just having trouble rendering emissive meshes or is it something more complex?
IMS
IMS16mo ago
RV has never been able to fully do PBR to my knowledge, lemme see
Sinan
SinanOP16mo ago
Thanks for looking! 😊 I mean, isn't integrated PBR PBR? It looks hella good
IMS
IMS16mo ago
what version of RV are you on?
Sinan
SinanOP16mo ago
The latest github master branch I cloned it
IMS
IMS16mo ago
Integrated PBR is PBR, but all the PBR is done in code and not in textures it's probably a rethinking voxels bug
Sinan
SinanOP16mo ago
May I ask the difference? For me (who doesn't know anything) it seems as if coding a PBR shader and then hardcoding the surface properties doesnt seem too far off of loading according textures
IMS
IMS16mo ago
you get more fine grained control there's no limit as to what pixel you're on or what the options are
Sinan
SinanOP16mo ago
Okay, with labPBR I get some pretty damn awesome results 😍
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
This is with a completely white specular map again
Sinan
SinanOP16mo ago
LabPBR Material Standard
This is a standard covering the material data storage using only two textures in resource packs, as well as the decoding done by shader packs. They can use this data for physically based rendering (PBR), but be aware that normal and specular textures themselves are not directly related to PBR in any way.
Sinan
SinanOP16mo ago
But labPBR suggests that a green channel with 255 is metal, however my object looks like a glossy dielectric
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
yep, use Kappa shaders to test those
Sinan
SinanOP16mo ago
Also hold up, RV works fine with labPBR, it was just that the default pack did not make the sea lanterns emissive
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
oh nice weird
Sinan
SinanOP16mo ago
😍 I LOVE IT okay this looks way more metallic I guess :Flushed_AE:
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
that's really nice
Sinan
SinanOP16mo ago
Thats SO NICE So you are saying rethinking voxels does not support metallics atm?
IMS
IMS16mo ago
complementary reimagined, the original, doesn't iirc it's not planned because it's too complex
Sinan
SinanOP16mo ago
Ah that's such a bummer Before I thank you a million for everything, I have two final minor questions :) This is Kappa's shaders:
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
And this is rethinking voxels:
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Is it just me or does Kappa seem to correctly map the normal map and rethinking voxels somehow fails?
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
rethinking voxels: there is some UV mapping gone wrong, let me see if I can get the same result in Kappa
IMS
IMS16mo ago
rethinking voxels doesn't have it as advanced so i wouldn't doubt it
Sinan
SinanOP16mo ago
Yup, kappa is rendering it correctly Hm, in general you mean? So their UV map code for normal maps is off but for the albedo texture not?
IMS
IMS16mo ago
yeah does it also happen on complementary reimagined? if so, report it there if not, report it to rethinking voxels
Sinan
SinanOP16mo ago
Huh, that should be easy to fix though right?
IMS
IMS16mo ago
maybe, maybe not
Sinan
SinanOP16mo ago
Yeah it does actually I will do a GitHub issue (or is there a better way?)
Sinan
SinanOP16mo ago
Ah great, thank you :) Okay great, then my second question How can I enable smooth shading for my built mesh? (I don't need smoothing groups, double vertices at sharp faces will suffice I think, the model comes with that)
IMS
IMS16mo ago
you'd probably need to edit the mesh unless you mean with shaders it's not smoothed
Sinan
SinanOP16mo ago
Actually now that you say it Let me try one more mesh But Kappa seems to be the all round winner, it seems to shade the mesh perfectly smooth Again seems to be a Complementary 'issue'
IMS
IMS16mo ago
kappa is one of the only shaders with 100% labPBR support, yeah Arc is a very close second, if you want to look into that
Sinan
SinanOP16mo ago
No actually it also doesn't
IMS
IMS16mo ago
No description
Sinan
SinanOP16mo ago
:o OMG what resource pack is this?
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
then the mesh is probably bad
Sinan
SinanOP16mo ago
It isn't
IMS
IMS16mo ago
hm
Sinan
SinanOP16mo ago
Probably my OBJ loading though Perhaps? Idk Or the renderlayer Which makes total sense to me, you wouldn't want to render smooth block edges As in you also don't want to have double vertices with blocks etc
IMS
IMS16mo ago
sadly i wouldn't know much about that if you want to look more into it renderdoc is your friend it can show you all GL state during the render
Sinan
SinanOP16mo ago
Wait woah is that a debug tool? The mesh in question in blender:
IMS
IMS16mo ago
yep, it's amazing
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
with renderdoc you can literally scroll through how the game renders, and see every part
No description
IMS
IMS16mo ago
as well as what the GPU is doing and/or thinking at that moment though it's quite a chore to set up sadly
Sinan
SinanOP16mo ago
oh my... I'm installing it rn
IMS
IMS16mo ago
yeah not sure then
Sinan
SinanOP16mo ago
I bet it's some single GL or shader flag or something
IMS
IMS16mo ago
you'll need to grab the launch arguments for the game, which is... annoying, to say the least maybe?
Sinan
SinanOP16mo ago
But just to be sure, the buffer builder has no way or order to enable smooth shading, the interpolation is all on the shader right?
IMS
IMS16mo ago
one quick check how big is the texture
Sinan
SinanOP16mo ago
1k
IMS
IMS16mo ago
ok, hm...
Sinan
SinanOP16mo ago
Nvm 2k, sorry I mixed something up
IMS
IMS16mo ago
it's fine, still that should work?
Sinan
SinanOP16mo ago
nvm I do not load the roughness, both my maps are 2k In which sense do you mean that?
IMS
IMS16mo ago
i'm just looking into comp reimagined's settings i'm honestly not sure what would cause such a bug
Sinan
SinanOP16mo ago
Ah you mean the UV thing, that's so nice of you!
IMS
IMS16mo ago
oh no i meant the shading i can look into uv's too, but i wouldn't know much
Sinan
SinanOP16mo ago
Ah huh, smooth shading is not dependent on normal map, it's a shading feature Or am I misunderstanding you right now?
IMS
IMS16mo ago
i meant i was looking into shading before looking into uv's
Sinan
SinanOP16mo ago
I am sorry, regarding which problem exactly? This one?
IMS
IMS16mo ago
nah, this one
Sinan
SinanOP16mo ago
You know what I average the normals out when baking my mesh (average of each3 vertices) I will try removing that Nope
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Still that
IMS
IMS16mo ago
Then if I had to guess it’s a shader bug since iris really doesn’t influence those things
Sinan
SinanOP16mo ago
Hm, maybe I exported it wrong... Let me look into that
Sinan
SinanOP16mo ago
Nope. I tried all different export settings, but when reimporting into blender it works and in minecraft it doesn't. Did you find anything in the shading? If I am not mistaken they just need to lerp between the vertex normal values and that's it
No description
Sinan
SinanOP16mo ago
I guess my OBJ parser works fine...
if (line.startsWith("v ")) {
String[] data = line.split(" ");
vertices.add(new Vec3d(
Double.parseDouble(data[1]),
Double.parseDouble(data[2]),
Double.parseDouble(data[3])
));
} else if (line.startsWith("vt ")) {
String[] data = line.split(" ");
uvs.add(new Vec2f(
Float.parseFloat(data[1]),
Float.parseFloat(data[2])
));
} else if (line.startsWith("vn ")) {
String[] data = line.split(" ");
normals.add(new Vec3d(
Double.parseDouble(data[1]),
Double.parseDouble(data[2]),
Double.parseDouble(data[3])
));
} else if (line.startsWith("f ")) {
String[] data = line.split(" ");
// Each vertex in the face has 3 attributes (v/vt/vn), so we multiply by 3
int[] face = new int[(data.length - 1) * 3];
Arrays.fill(face, -1);
for (int i = 1; i < data.length; i++) {
String[] faceData = data[i].split("/");
face[(i-1)*3] = Integer.parseInt(faceData[0])-1;
if (faceData.length > 1 && !faceData[1].isEmpty()) {
face[(i-1)*3 + 1] = Integer.parseInt(faceData[1])-1;
}
if (faceData.length > 2) {
face[(i-1)*3 + 2] = Integer.parseInt(faceData[2])-1;
}
}
faces.add(face);
}
if (line.startsWith("v ")) {
String[] data = line.split(" ");
vertices.add(new Vec3d(
Double.parseDouble(data[1]),
Double.parseDouble(data[2]),
Double.parseDouble(data[3])
));
} else if (line.startsWith("vt ")) {
String[] data = line.split(" ");
uvs.add(new Vec2f(
Float.parseFloat(data[1]),
Float.parseFloat(data[2])
));
} else if (line.startsWith("vn ")) {
String[] data = line.split(" ");
normals.add(new Vec3d(
Double.parseDouble(data[1]),
Double.parseDouble(data[2]),
Double.parseDouble(data[3])
));
} else if (line.startsWith("f ")) {
String[] data = line.split(" ");
// Each vertex in the face has 3 attributes (v/vt/vn), so we multiply by 3
int[] face = new int[(data.length - 1) * 3];
Arrays.fill(face, -1);
for (int i = 1; i < data.length; i++) {
String[] faceData = data[i].split("/");
face[(i-1)*3] = Integer.parseInt(faceData[0])-1;
if (faceData.length > 1 && !faceData[1].isEmpty()) {
face[(i-1)*3 + 1] = Integer.parseInt(faceData[1])-1;
}
if (faceData.length > 2) {
face[(i-1)*3 + 2] = Integer.parseInt(faceData[2])-1;
}
}
faces.add(face);
}
IMS
IMS16mo ago
sadly, no didn't find anything
Sinan
SinanOP16mo ago
Okay so they do interpolate nicely there?
IMS
IMS16mo ago
however, Create has a custom OBJ loader i've helped with if you're interested in that no i just don't know why
Sinan
SinanOP16mo ago
Hm, then the shader doesn't support smooth shading at all right?
IMS
IMS16mo ago
it should which is what confuses me
Sinan
SinanOP16mo ago
Wait, should the vanilla shader also do it? Because it doesn't for me
IMS
IMS16mo ago
what do you mean? smooth shading doesn't work even in vanilla?
Sinan
SinanOP16mo ago
Okay I didn't know that
IMS
IMS16mo ago
no, i thought that's what you were saying? i was asking a question lol
Sinan
SinanOP16mo ago
Oh lol, I was just asking if vanilla does by default, that would result in my mesh being built incorrectly Speaking of:
IMS
IMS16mo ago
well, you can check just press K and see if it's still shaded badly
Sinan
SinanOP16mo ago
Yes please, thank you very much :) I already wrote mine, could you please take a look over it? yup I did, its not smooth either
IMS
IMS16mo ago
sadly, i haven't really worked on it in a while ok that's very important one sec
Sinan
SinanOP16mo ago
public class OBJParser {
public ArrayList<Vec3d> vertices = new ArrayList<>();
public ArrayList<Vec2f> uvs = new ArrayList<>();
public ArrayList<Vec3d> normals = new ArrayList<>();
public ArrayList<int[]> faces = new ArrayList<>();

public void loadOBJ(String fileName) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("v ")) {
String[] data = line.split(" ");
vertices.add(new Vec3d(
Double.parseDouble(data[1]),
Double.parseDouble(data[2]),
Double.parseDouble(data[3])
));
} else if (line.startsWith("vt ")) {
String[] data = line.split(" ");
uvs.add(new Vec2f(
Float.parseFloat(data[1]),
Float.parseFloat(data[2])
));
} else if (line.startsWith("vn ")) {
String[] data = line.split(" ");
normals.add(new Vec3d(
Double.parseDouble(data[1]),
Double.parseDouble(data[2]),
Double.parseDouble(data[3])
));
} else if (line.startsWith("f ")) {
String[] data = line.split(" ");
// Each vertex in the face has 3 attributes (v/vt/vn), so we multiply by 3
int[] face = new int[(data.length - 1) * 3];
Arrays.fill(face, -1);
for (int i = 1; i < data.length; i++) {
String[] faceData = data[i].split("/");
face[(i-1)*3] = Integer.parseInt(faceData[0])-1;
if (faceData.length > 1 && !faceData[1].isEmpty()) {
face[(i-1)*3 + 1] = Integer.parseInt(faceData[1])-1;
}
if (faceData.length > 2) {
face[(i-1)*3 + 2] = Integer.parseInt(faceData[2])-1;
}
}
faces.add(face);
}
}
reader.close();
}
}
public class OBJParser {
public ArrayList<Vec3d> vertices = new ArrayList<>();
public ArrayList<Vec2f> uvs = new ArrayList<>();
public ArrayList<Vec3d> normals = new ArrayList<>();
public ArrayList<int[]> faces = new ArrayList<>();

public void loadOBJ(String fileName) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("v ")) {
String[] data = line.split(" ");
vertices.add(new Vec3d(
Double.parseDouble(data[1]),
Double.parseDouble(data[2]),
Double.parseDouble(data[3])
));
} else if (line.startsWith("vt ")) {
String[] data = line.split(" ");
uvs.add(new Vec2f(
Float.parseFloat(data[1]),
Float.parseFloat(data[2])
));
} else if (line.startsWith("vn ")) {
String[] data = line.split(" ");
normals.add(new Vec3d(
Double.parseDouble(data[1]),
Double.parseDouble(data[2]),
Double.parseDouble(data[3])
));
} else if (line.startsWith("f ")) {
String[] data = line.split(" ");
// Each vertex in the face has 3 attributes (v/vt/vn), so we multiply by 3
int[] face = new int[(data.length - 1) * 3];
Arrays.fill(face, -1);
for (int i = 1; i < data.length; i++) {
String[] faceData = data[i].split("/");
face[(i-1)*3] = Integer.parseInt(faceData[0])-1;
if (faceData.length > 1 && !faceData[1].isEmpty()) {
face[(i-1)*3 + 1] = Integer.parseInt(faceData[1])-1;
}
if (faceData.length > 2) {
face[(i-1)*3 + 2] = Integer.parseInt(faceData[2])-1;
}
}
faces.add(face);
}
}
reader.close();
}
}
That's the whole parser Looks fine ig, worked to the point that you saw above And here is baking the mesh and uploading it to the GPU:
IMS
IMS16mo ago
i think you're just running into the "no smooth lighting" vanilla issue, yeah which can't be fixed really
Sinan
SinanOP16mo ago
public static VertexBuffer createVbo(BufferBuilder.BuiltBuffer builder, VertexBuffer.Usage expectedUsage) {
VertexBuffer buffer = new VertexBuffer(expectedUsage);
buffer.bind();
buffer.upload(builder);
VertexBuffer.unbind();
return buffer;
}
public static VertexBuffer createVbo(BufferBuilder.BuiltBuffer builder, VertexBuffer.Usage expectedUsage) {
VertexBuffer buffer = new VertexBuffer(expectedUsage);
buffer.bind();
buffer.upload(builder);
VertexBuffer.unbind();
return buffer;
}
public void bakeModel(String modelName, OBJParser objParser) {
// Create a new BufferBuilder with an initial capacity of 512.
int bufferSize = calculateBufferSize(objParser.vertices.size(), objParser.faces.size());
System.out.println("BUFFER SIZE!: " + bufferSize);

Map<Integer, VertexBuffer> bufferMap = new HashMap<>();


//iterate through light possibilities
// TODO: well, fix lighting...
for(int blockLight=0; blockLight < 16; blockLight++) {
for(int skyLight=0; skyLight < 16; skyLight++) {
if (arrayContains(blockLightSteps, blockLight) && arrayContains(skyLightSteps, skyLight)) {
BufferBuilder bufferBuilder = new BufferBuilder(64);
// Start building triangles with position, color, texture, overlay, light, and normal.
bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL);//POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL

int light = packLight(blockLight, skyLight);
System.out.println("Packed baked light: " + light);
// Iterate over all faces.
for (int[] face : objParser.faces) {
// Each face has 3 vertices.
for (int i = 1; i < face.length / 3 - 1; i++) {
Vec3d v1 = objParser.vertices.get(face[0]);
Vec3d normal1 = objParser.normals.get(face[2]);

Vec3d v2 = objParser.vertices.get(face[i * 3]);
Vec3d normal2 = objParser.normals.get(face[i * 3 + 2]);

Vec3d v3 = objParser.vertices.get(face[(i + 1) * 3]);
Vec3d normal3 = objParser.normals.get(face[(i + 1) * 3 + 2]);
public void bakeModel(String modelName, OBJParser objParser) {
// Create a new BufferBuilder with an initial capacity of 512.
int bufferSize = calculateBufferSize(objParser.vertices.size(), objParser.faces.size());
System.out.println("BUFFER SIZE!: " + bufferSize);

Map<Integer, VertexBuffer> bufferMap = new HashMap<>();


//iterate through light possibilities
// TODO: well, fix lighting...
for(int blockLight=0; blockLight < 16; blockLight++) {
for(int skyLight=0; skyLight < 16; skyLight++) {
if (arrayContains(blockLightSteps, blockLight) && arrayContains(skyLightSteps, skyLight)) {
BufferBuilder bufferBuilder = new BufferBuilder(64);
// Start building triangles with position, color, texture, overlay, light, and normal.
bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL);//POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL

int light = packLight(blockLight, skyLight);
System.out.println("Packed baked light: " + light);
// Iterate over all faces.
for (int[] face : objParser.faces) {
// Each face has 3 vertices.
for (int i = 1; i < face.length / 3 - 1; i++) {
Vec3d v1 = objParser.vertices.get(face[0]);
Vec3d normal1 = objParser.normals.get(face[2]);

Vec3d v2 = objParser.vertices.get(face[i * 3]);
Vec3d normal2 = objParser.normals.get(face[i * 3 + 2]);

Vec3d v3 = objParser.vertices.get(face[(i + 1) * 3]);
Vec3d normal3 = objParser.normals.get(face[(i + 1) * 3 + 2]);
/*
// flat
Vec3d normal = new Vec3d(
(normal1.x + normal2.x + normal3.x) / 3.0,
(normal1.y + normal2.y + normal3.y) / 3.0,
(normal1.z + normal2.z + normal3.z) / 3.0
);
Vec3d[] normals = new Vec3d[]{normal, normal, normal};
*/

// smooth
Vec3d[] normals = new Vec3d[]{normal1, normal2, normal3};

Vec3d[] vertices = {v1, v2 ,v3};

Vec2f uv1 = objParser.uvs.get(face[1]);
uv1 = new Vec2f(uv1.x, 1.0f - uv1.y); // flip V coordinate

Vec2f uv2 = objParser.uvs.get(face[i * 3 + 1]);
uv2 = new Vec2f(uv2.x, 1.0f - uv2.y); // flip V coordinate

Vec2f uv3 = objParser.uvs.get(face[(i + 1) * 3 + 1]);
uv3 = new Vec2f(uv3.x, 1.0f - uv3.y); // flip V coordinate

Vec2f[] uvs = {uv1, uv2, uv3};

for (int j = 0; j < 3; j++) {
// position
bufferBuilder.vertex(vertices[j].x, vertices[j].y, vertices[j].z)
.color(1.0f, 1.0f, 1.0f, 1.0f)
.texture(uvs[j].x, uvs[j].y)
.overlay(OverlayTexture.DEFAULT_UV)
.light(light)
.normal((float) normals[j].x, (float) normals[j].y, (float) normals[j].z)
.next();
}
}
}

BufferBuilder.BuiltBuffer builtBuffer = bufferBuilder.end();
bufferMap.put(light, createVbo(builtBuffer, VertexBuffer.Usage.STATIC));
}
}
}
modelBuffers.put(modelName, bufferMap);
}
/*
// flat
Vec3d normal = new Vec3d(
(normal1.x + normal2.x + normal3.x) / 3.0,
(normal1.y + normal2.y + normal3.y) / 3.0,
(normal1.z + normal2.z + normal3.z) / 3.0
);
Vec3d[] normals = new Vec3d[]{normal, normal, normal};
*/

// smooth
Vec3d[] normals = new Vec3d[]{normal1, normal2, normal3};

Vec3d[] vertices = {v1, v2 ,v3};

Vec2f uv1 = objParser.uvs.get(face[1]);
uv1 = new Vec2f(uv1.x, 1.0f - uv1.y); // flip V coordinate

Vec2f uv2 = objParser.uvs.get(face[i * 3 + 1]);
uv2 = new Vec2f(uv2.x, 1.0f - uv2.y); // flip V coordinate

Vec2f uv3 = objParser.uvs.get(face[(i + 1) * 3 + 1]);
uv3 = new Vec2f(uv3.x, 1.0f - uv3.y); // flip V coordinate

Vec2f[] uvs = {uv1, uv2, uv3};

for (int j = 0; j < 3; j++) {
// position
bufferBuilder.vertex(vertices[j].x, vertices[j].y, vertices[j].z)
.color(1.0f, 1.0f, 1.0f, 1.0f)
.texture(uvs[j].x, uvs[j].y)
.overlay(OverlayTexture.DEFAULT_UV)
.light(light)
.normal((float) normals[j].x, (float) normals[j].y, (float) normals[j].z)
.next();
}
}
}

BufferBuilder.BuiltBuffer builtBuffer = bufferBuilder.end();
bufferMap.put(light, createVbo(builtBuffer, VertexBuffer.Usage.STATIC));
}
}
}
modelBuffers.put(modelName, bufferMap);
}
Ah okay, thought that I might check against vanilla if it did support smooth @IMS I contacted the complementary lead, we found the UV issue :) Disabling parallax occlusion mapping fixes the normal map
IMS
IMS16mo ago
nice
Sinan
SinanOP16mo ago
:)) Okay, so may I ask did you take a quick glance at that code? Imo it looks correct, nothing much can be done wrong with supplying normals I would really like to fix smooth shading... I understand it the way that no GL flag changes smooth shading but actually the per vertex normal? Idk Hey, I finally solved the smooth shading!!!
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
@IMS Hi! :) However, I found a super weird bug, even with shaders When I look at this mesh from here, its fine
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
However the more I look from the top, the darker it gets
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
The following is a sequence of decreasing camera angle. It seems as if the camera angle is the only thing changing lighting, NOT THE VIEWING ANGLE
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Note that in the middle, it almost looks flat, not shaded at all With BSL the angles are different, though the same behaviour
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
With Kappa shaders, it's flat from all angles
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Do you know what's going on here?
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
This is kappa when exporting the mesh as flat shaded
IMS
IMS16mo ago
i assume it's related to normals normals are in view space
Sinan
SinanOP16mo ago
(there is no normal map btw) Hm, do you have an idea why in Kappa for example it's completely unshaded ("flat") when exporting as a smooth mesh? Do these mesh normals look right to you? So, is my mesh built correctly? Between smooth and flat, my code stays the same, only the exported values are different, does that mean my mesh building code is correct? I want to exclude mesh building factors, maybe it's where I subscribe my rendering event or something Ok, so the whole mesh acts as a flat mirror
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
it's kinda rotated by 90 degrees etc I guess my mesh building code is definitely doing something sketchy with exported shaded meshes? it seems as if even the normalmaps have been overwritten... What could the cause of that whole smooth shading be?
Sinan
SinanOP16mo ago
(normal map normally makes spikes, which worked with flat shading)
No description
Sinan
SinanOP16mo ago
nvm, also happens on flat exported meshes when they are metallic I also noticed super weird behaviour, some smooth exported meshes are rendered flat, some are not (same mesh but exporting twice whilst no process is accessing the file) I will rework my parser again... Hm, I am really unsure When I export as obj, it's always flat When I export as obj(legacy) it looks like this with rethinking voxels:
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
(should be a normal only color diffuse map, nothing more) different angle
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
different angle again
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
this is vanilla (dark areas change with me moving around, def not how it's supposed to look)
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
BSL is the only shader apparently rendering it like its supposed to (I am super confused)
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
OK I definitely need your help hedge hog. I just found out: when loading a color map only, it is being shaded smoothly. When I load a color and specular map, the mesh is being rendered completely flat. When loading color, specular and normal, it has the werid effect being shown in my pistol screenshots
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
(clouds are 90 degree rotated)
IMS
IMS16mo ago
that seems like almost certainly a shader bug
Sinan
SinanOP16mo ago
But it's consistent across all shaders I have installed
IMS
IMS16mo ago
the only thing I can think of is if we're somehow screwing up the tangents we do automatic tangent calculation based on normal + uv
IMS
IMS16mo ago
here, download supertester from https://github.com/sp614x/supertester
GitHub
GitHub - sp614x/SuperTester: Super tester shader pack
Super tester shader pack. Contribute to sp614x/SuperTester development by creating an account on GitHub.
IMS
IMS16mo ago
apply it as a shader, and then set GBUFFER_DEBUG in the shader settings to at_tangent see if it looks right
Sinan
SinanOP16mo ago
Yes thanks I am doing that rn 🙏 :)
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Color, Specular, Normal -> Black from all sides Let me check for all texture combinations (except normal map only, should I also set that up)?
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
^ Color and specular only
IMS
IMS16mo ago
ok, that's not good... wait a second lemme scroll up to your code again lol
Sinan
SinanOP16mo ago
I will send you the newest one! I did a complete rework
IMS
IMS16mo ago
hm, your render layer is corect
Sinan
SinanOP16mo ago
(its better readable and actually does make smooth meshes somehow)
IMS
IMS16mo ago
the only reason tangent should be null is if your code is somehow skipping it which it isn't afaik
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Tangents are the same for color only and color+specular
IMS
IMS16mo ago
do they look correct? so it's color+normal+specular that's broken only?
Sinan
SinanOP16mo ago
I can not tell. Should I export flat only? Should they be identical? (I am doing that rn)
IMS
IMS16mo ago
do the colors match up with the world well actually nvm does each side have it's own color it should look kinda like a color sphere
Sinan
SinanOP16mo ago
Well then it's probably wrong, if you look here it looks off I provided 360 screenshots, do you need more angles?
IMS
IMS16mo ago
no, i'm just confused i don't know how you could be breaking tangent calculations
Sinan
SinanOP16mo ago
It's booting up, I am testing against flat exported mesh
IMS
IMS16mo ago
do normals look right? and i mean in the shader
Sinan
SinanOP16mo ago
I will provide my code in a bit
IMS
IMS16mo ago
switch gbuffer_debug to glx_normals
Sinan
SinanOP16mo ago
Let me test, one sec Wait please, I just found out that exporting obj vs obj(legacy) makes it flat and smooth respecitvely I am sorry for the delay, I can't hotswap, need to reboot mc when changing models and I can only test the normals when the mesh is smooth in vanilla too which it isnt rn HUH? Now with color only its also black with tangent
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
this is color only texture Before it was not like that, I presumably didn't change anything I will give you normals in a second, just need to confirm that the mesh behind the normals is 'correct', at least coherent ??? after restarting with another color only texture the tangents are back and it's completely flat [EDITED] I am so sorry for all the messages but I believe verbosity is key to strange problems like this Absolute, consistent findings: Booting into world with vanilla shaders loaded + color only texture -> smooth shading in vanilla (still looking slightly weird with weird dark patches) black tangents correct shading in bsl (only color, idk about reflections) incorrect shading with kappa and rethinking voxels Booting with vanilla shaders loaded + color and specular texture -> smooth shading in vanilla (still looking slightly weird with weird dark patches) black tangents incorrect reflections (90 degree angle etc) Booting with vanilla shaders loaded + color, specular and normal texture -> same findings AHA Booting with BSL loaded initially -> Renders mesh flat in every shader including vanilla??? Therefore giving it tangent colors now
IMS
IMS16mo ago
how??? that doesn't make sense
Sinan
SinanOP16mo ago
😭 IDK, booting with BSL loaded makes it flat with every possible texture So, to conclude, it was NOT a texture issue, it was an issue with which shader I boot minecraft. Keep in mind, BSL messes up reflections, but diffuse seems to shade correct! (every other shader though messes up even diffuse only) Here are the normals (for vanilla loaded, black tangents):
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
What was I talking, that was default interpolation behaviour, yes, the normals are correct, at least when I boot the game in vanilla shaders. The tangents seem to be the problem: Rendering code:
.register(context -> {
MinecraftClient mc = MinecraftClient.getInstance();
RenderLayer renderLayer = NewRenderLayer.getNewLayer(new Identifier("luminance", "textures/cyan.png"));
VertexConsumerProvider.Immediate immediate = mc.getBufferBuilders().getEntityVertexConsumers();
VertexConsumer vertexConsumer = immediate.getBuffer(renderLayer);

context.matrixStack().push();
context.matrixStack().translate(-context.camera().getPos().x, -context.camera().getPos().y, -context.camera().getPos().z);

if(!modelBuffers.containsKey("myModel")) {
try {
bakeModel("myModel", suzanne);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

VertexBuffer vertexBuffer = modelBuffers.get("myModel").get(newLight);

if(vertexBuffer != null) {
renderLayer.startDrawing();
vertexBuffer.bind();
shaderLights[0] = ShaderLights.lastShaderLights[0];
shaderLights[1] = ShaderLights.lastShaderLights[1];

context.matrixStack().push();
//context.matrixStack().multiply(new Quaternionf().rotateYXZ(45,0,0));
//context.matrixStack().scale(0.3f,0.3f,0.3f);
//context.matrixStack().scale(3f,3f,3f);
//context.matrixStack().translate(2,0,0);

RenderSystem.setShaderLights(shaderLights[0], shaderLights[1]);
Matrix4f m4f = new Matrix4f(context.matrixStack().peek().getPositionMatrix());
var matrix = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(m4f);


vertexBuffer.draw(matrix, context.projectionMatrix(), GameRenderer.getRenderTypeEntitySolidProgram());

renderLayer.endDrawing();
context.matrixStack().pop();
}

context.matrixStack().pop();
});
.register(context -> {
MinecraftClient mc = MinecraftClient.getInstance();
RenderLayer renderLayer = NewRenderLayer.getNewLayer(new Identifier("luminance", "textures/cyan.png"));
VertexConsumerProvider.Immediate immediate = mc.getBufferBuilders().getEntityVertexConsumers();
VertexConsumer vertexConsumer = immediate.getBuffer(renderLayer);

context.matrixStack().push();
context.matrixStack().translate(-context.camera().getPos().x, -context.camera().getPos().y, -context.camera().getPos().z);

if(!modelBuffers.containsKey("myModel")) {
try {
bakeModel("myModel", suzanne);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

VertexBuffer vertexBuffer = modelBuffers.get("myModel").get(newLight);

if(vertexBuffer != null) {
renderLayer.startDrawing();
vertexBuffer.bind();
shaderLights[0] = ShaderLights.lastShaderLights[0];
shaderLights[1] = ShaderLights.lastShaderLights[1];

context.matrixStack().push();
//context.matrixStack().multiply(new Quaternionf().rotateYXZ(45,0,0));
//context.matrixStack().scale(0.3f,0.3f,0.3f);
//context.matrixStack().scale(3f,3f,3f);
//context.matrixStack().translate(2,0,0);

RenderSystem.setShaderLights(shaderLights[0], shaderLights[1]);
Matrix4f m4f = new Matrix4f(context.matrixStack().peek().getPositionMatrix());
var matrix = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(m4f);


vertexBuffer.draw(matrix, context.projectionMatrix(), GameRenderer.getRenderTypeEntitySolidProgram());

renderLayer.endDrawing();
context.matrixStack().pop();
}

context.matrixStack().pop();
});
That's my whole rendering code. Ignore the .get(newLight) part, I was too dumb to change vertex lights after building the buffer, so I just prebaked many possible block and skylight combinations and put them in a hashmap like an ape.
public static RenderLayer getNewLayer(Identifier texture) {
return NewRenderLayer.of("newlasl", VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, VertexFormat.DrawMode.TRIANGLES, 256, false, false, MultiPhaseParameters.builder().program(ENTITY_SOLID_PROGRAM).texture(new RenderPhase.Texture((Identifier)texture, false, false)).transparency(RenderPhase.NO_TRANSPARENCY).lightmap(ENABLE_LIGHTMAP).build(false));
}
public static RenderLayer getNewLayer(Identifier texture) {
return NewRenderLayer.of("newlasl", VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, VertexFormat.DrawMode.TRIANGLES, 256, false, false, MultiPhaseParameters.builder().program(ENTITY_SOLID_PROGRAM).texture(new RenderPhase.Texture((Identifier)texture, false, false)).transparency(RenderPhase.NO_TRANSPARENCY).lightmap(ENABLE_LIGHTMAP).build(false));
}
So, I booted into vanilla, THEN loaded BSL (or Kappa or even the supertester) and then baked the mesh. The mesh builds flat.
IMS
IMS16mo ago
wait
Sinan
SinanOP16mo ago
This must be Iris, when any shader is loaded
IMS
IMS16mo ago
are you baking the mesh once and then rerendering it? that must be why Iris assumes you will be doing per-frame meshing as MC itself does
Sinan
SinanOP16mo ago
Yes. Here is the baking code:
public static VertexBuffer createVbo(BufferBuilder.BuiltBuffer builder, VertexBuffer.Usage expectedUsage) {
VertexBuffer buffer = new VertexBuffer(expectedUsage);
buffer.bind();
buffer.upload(builder);
VertexBuffer.unbind();
return buffer;
}

public void bakeModel(String modelName, Mesh mesh) throws Exception {
try {
Map<Integer, VertexBuffer> bufferMap = new HashMap<>();

// Iterate through light possibilities
for (int blockLight = 0; blockLight < 16; blockLight++) {
for (int skyLight = 0; skyLight < 16; skyLight++) {
if (arrayContains(blockLightSteps, blockLight) && arrayContains(skyLightSteps, skyLight)) {
int light = packLight(blockLight, skyLight);

BufferBuilder bufferBuilder = new BufferBuilder(64);
bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL);

// Iterate over all faces.
for (Mesh.Face face : mesh.faces) {
for (int index = 0; index < 3; index++) {
Vec3d vertex = mesh.vertices.get(face.vertexIndices[index]);
Vec2f uv = mesh.uvs.get(face.uvIndices[index]);
uv = new Vec2f(uv.x, 1.0f - uv.y); // flip V coordinate

Vec3d normal = mesh.normals.get(face.normalIndices[index]);
boolean smooth = face.smooth;


bufferBuilder.vertex(vertex.x, vertex.y, vertex.z)
.color(1.0f, 1.0f, 1.0f, 1.0f)
.texture(uv.x, uv.y)
.overlay(OverlayTexture.DEFAULT_UV)
.light(light)
.normal((float) normal.x, (float) normal.y, (float) normal.z)
.next();
}
}

BufferBuilder.BuiltBuffer builtBuffer = bufferBuilder.end();
bufferMap.put(light, createVbo(builtBuffer, VertexBuffer.Usage.STATIC));
}
}
}

modelBuffers.put(modelName, bufferMap);
} catch(IndexOutOfBoundsException e) {
throw e;//new Exception("Please triangulate the mesh!");
}
}
public static VertexBuffer createVbo(BufferBuilder.BuiltBuffer builder, VertexBuffer.Usage expectedUsage) {
VertexBuffer buffer = new VertexBuffer(expectedUsage);
buffer.bind();
buffer.upload(builder);
VertexBuffer.unbind();
return buffer;
}

public void bakeModel(String modelName, Mesh mesh) throws Exception {
try {
Map<Integer, VertexBuffer> bufferMap = new HashMap<>();

// Iterate through light possibilities
for (int blockLight = 0; blockLight < 16; blockLight++) {
for (int skyLight = 0; skyLight < 16; skyLight++) {
if (arrayContains(blockLightSteps, blockLight) && arrayContains(skyLightSteps, skyLight)) {
int light = packLight(blockLight, skyLight);

BufferBuilder bufferBuilder = new BufferBuilder(64);
bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL);

// Iterate over all faces.
for (Mesh.Face face : mesh.faces) {
for (int index = 0; index < 3; index++) {
Vec3d vertex = mesh.vertices.get(face.vertexIndices[index]);
Vec2f uv = mesh.uvs.get(face.uvIndices[index]);
uv = new Vec2f(uv.x, 1.0f - uv.y); // flip V coordinate

Vec3d normal = mesh.normals.get(face.normalIndices[index]);
boolean smooth = face.smooth;


bufferBuilder.vertex(vertex.x, vertex.y, vertex.z)
.color(1.0f, 1.0f, 1.0f, 1.0f)
.texture(uv.x, uv.y)
.overlay(OverlayTexture.DEFAULT_UV)
.light(light)
.normal((float) normal.x, (float) normal.y, (float) normal.z)
.next();
}
}

BufferBuilder.BuiltBuffer builtBuffer = bufferBuilder.end();
bufferMap.put(light, createVbo(builtBuffer, VertexBuffer.Usage.STATIC));
}
}
}

modelBuffers.put(modelName, bufferMap);
} catch(IndexOutOfBoundsException e) {
throw e;//new Exception("Please triangulate the mesh!");
}
}
IMS
IMS16mo ago
yeah... that's a critical problem
Sinan
SinanOP16mo ago
Basically it: - makes a new BufferBuilder, begins it - takes all faces of the mesh and builds it with the bufferBuilder - ends the bufferBuilder, creates a VBO (which uploads it to GPU) and yeah
IMS
IMS16mo ago
the problem comes from the fact that with shaders off, Iris doesn't produce the extra info like tangents because it's a waste
Sinan
SinanOP16mo ago
Per frame meshing is super inefficient for static meshes
IMS
IMS16mo ago
and if you force it to produce that extra info vanilla will crash i don't think you need to do it per frame but per-reload somehow when a shader is changed
Sinan
SinanOP16mo ago
Hm, does that make sense? I think I don't get your point After I have long loaded any shader, I then shift (which bakes the mesh) and it's still flat So basically all shaders are already loaded, then I bake, then it's flat If I build in vanilla at any points it's smooth (correct I guess) but Iris doesn't provide tangents
IMS
IMS16mo ago
yeah, i don't know why that would happen...
Sinan
SinanOP16mo ago
Hm So, the whole bufferBuilder has nothing to do with shaders nor GPUs, so that's excluded
public static VertexBuffer createVbo(BufferBuilder.BuiltBuffer builder, VertexBuffer.Usage expectedUsage) {
VertexBuffer buffer = new VertexBuffer(expectedUsage);
buffer.bind();
buffer.upload(builder);
VertexBuffer.unbind();
return buffer;
}
public static VertexBuffer createVbo(BufferBuilder.BuiltBuffer builder, VertexBuffer.Usage expectedUsage) {
VertexBuffer buffer = new VertexBuffer(expectedUsage);
buffer.bind();
buffer.upload(builder);
VertexBuffer.unbind();
return buffer;
}
That's one of the 'variables' changing when a shader is loaded
IMS
IMS16mo ago
it does iris replaces major portions of it with shaders on that's where all of the tricks take place
Sinan
SinanOP16mo ago
Well up until uploading the BufferBuilder is completely CPU side right?
IMS
IMS16mo ago
yep but Iris does a bunch of checks
Sinan
SinanOP16mo ago
Oh So that must be it
IMS
IMS16mo ago
it's where tangents are added to the mix
Sinan
SinanOP16mo ago
Damn
IMS
IMS16mo ago
you have to somehow make it remesh on a shader reload
Sinan
SinanOP16mo ago
Just out of curiosity, what are the tangents for exactly? Does vanilla have them?
IMS
IMS16mo ago
pbr and no it's a critical part of PBR lighting models
Sinan
SinanOP16mo ago
Okay... Now it makes sense to me, the testing results above I will take a look into iris' source code
IMS
IMS16mo ago
👍
Sinan
SinanOP16mo ago
Before I do (so that I prime my knowledge, understand more) what does Iris do with BufferBuilders?
IMS
IMS16mo ago
you're looking for net.coderbot.iris.mixin.vertices
Sinan
SinanOP16mo ago
❤️
IMS
IMS16mo ago
that's where all the bufferbuilder stuff happens when you call endVertex for the third time, it goes through the whole triangle, computes a bunch of info, and adds backward to give the triangles info about it's own vertices
Sinan
SinanOP16mo ago
Which branch should I look into?
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
1.20-new
Sinan
SinanOP16mo ago
endVertex doesn't seem to exist in 1.20 Thank you
IMS
IMS16mo ago
we use mojmap names it's next in yarn
Sinan
SinanOP16mo ago
Oh I see, thanks!
Sinan
SinanOP16mo ago
Ah that's awesome 😍 And sorry for my rusty mixin understanding, but is that endVertex completely intercepted, so everything is being replaced by iris?
if (vertexAmount == 3) {
NormalHelper.computeFaceNormalTri(normal, polygon);
}
if (vertexAmount == 3) {
NormalHelper.computeFaceNormalTri(normal, polygon);
}
Yeah
IMS
IMS16mo ago
yep you're looking for computeTangent though prob since normal is right, isn't it?
Sinan
SinanOP16mo ago
Actually, it's just that Normals are correct in vanilla When shaders are loaded, normals are flat all of the sudden
IMS
IMS16mo ago
ok, yeah
Sinan
SinanOP16mo ago
Because of this Omg it seems as if I just need to remove that line What a blessing Tangents should be rebuilt automatically
IMS
IMS16mo ago
yep... but the problem is that's kinda important for other cases
Sinan
SinanOP16mo ago
Hm, for what exactly?
IMS
IMS16mo ago
I think we somehow need to add a flag that says to Iris "yes, these normals are right" Minecraft's normals are completely and utterly wrong Iris has to recreate them
Sinan
SinanOP16mo ago
But, Minecraft rarely uses tris right?
IMS
IMS16mo ago
it does the same thing for quads look below just a different function
Sinan
SinanOP16mo ago
I know, but what if we just removed the tris recalc? Then MC shall be good
IMS
IMS16mo ago
that might work, but there's a chance if a mod uses those normals it'll break I guess it's fine, though I'll remove itg
Sinan
SinanOP16mo ago
Thank you so much 😍 Actually Can I do a PR please :3 @IMS Only if it's okaty
IMS
IMS16mo ago
sure, but we usually apply fixes to the 1.18.2 branch first
Sinan
SinanOP16mo ago
Yayyy Shall I do a PR to that too?
IMS
IMS16mo ago
sure
Sinan
SinanOP16mo ago
❤️ What do you prefer, if I completely remove the line or if I comment it out and add a comment saying that for some mods with broken normals they need to recalculate their normals themselves?
IMS
IMS16mo ago
comment it plz
Sinan
SinanOP16mo ago
Sure! Ok I did the PRs :)
IMS
IMS16mo ago
i meant to do one to 1.18.2 lol don't worry, i'll fix it
Sinan
SinanOP16mo ago
Wait its also loading
IMS
IMS16mo ago
oh
Sinan
SinanOP16mo ago
I did both, just needed to copy the text over :) Oh, it was immediately closed?
IMS
IMS16mo ago
i merged the 1.18.2 one and closed the 1.20 one i'll do 1.20 when I update 1.20 to 1.18.2's code
Sinan
SinanOP16mo ago
Ah I see now, great, thank you! And thank you for letting me do the PR :) Regarding the 1.20 one (and I wanted to know that anyways for other mods), is there an easy way to host my mods from github repos? Or do I have to compile my branch to a jar?
IMS
IMS16mo ago
not really but once your mod is on modrinth, modrinth itself acts as a maven for all of your releases
Sinan
SinanOP16mo ago
Oh modrinth is so damn nice Other than that, can I somehow modImplement my local repo files?
IMS
IMS16mo ago
to iris? or to another mod
Sinan
SinanOP16mo ago
To any for that matter
IMS
IMS16mo ago
iris doesn't use gradle so it's quite different it uses a custom system made for minecraft
Sinan
SinanOP16mo ago
Oh I see, so I guess I will compile the branch manually
IMS
IMS16mo ago
probably best, yeah
Sinan
SinanOP16mo ago
Woah, sounds complicated And regarding my own other mods? I'd like to have API access without compiling to JARs
IMS
IMS16mo ago
modImplementation(files("filename.jar")) put filename.jar in your mod source folder
Sinan
SinanOP16mo ago
Oh great thanks! It must be compiled right?
IMS
IMS16mo ago
yep you can compile iris using one command java -jar brachyura-bootstrap-0.jar build
Sinan
SinanOP16mo ago
Great, thank you a lot! I will compile and see if the tangents work :D
IMS
IMS16mo ago
no problem! 1.20 isn't updated yet give me a few minutes lol i'm still on 1.19.4
Sinan
SinanOP16mo ago
Oh okay sure, thanks a lot :D
IMS
IMS16mo ago
should be up in a few minutes, watch #iris-updates for 1.20 to show up
Sinan
SinanOP16mo ago
Okay! :blush_AE:
IMS
IMS16mo ago
@Sinan up now, pull 1.20-new actually i'll just send you a jar
Sinan
SinanOP16mo ago
That's so nice of you 😍 Instantly! Thank you so much!
IMS
IMS16mo ago
it takes like 15 minutes for a new user to build iris due to the amount of downloads
Sinan
SinanOP16mo ago
I'm so excited ^^ Okayy, so not quite what we expected
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
This is vanilla Although the tangents are now there!
IMS
IMS16mo ago
that's really weird
Sinan
SinanOP16mo ago
BSL looks the same
IMS
IMS16mo ago
maybe with iris no longer there to supply normals it doesn't know what to do
Sinan
SinanOP16mo ago
Oh ofc!
IMS
IMS16mo ago
?
Sinan
SinanOP16mo ago
The mixin completely replaces the function right? I believe the normals might not even get saved from the beginning?
IMS
IMS16mo ago
lemme check
Sinan
SinanOP16mo ago
Ok sure me too! (idk what I am doing lol)
IMS
IMS16mo ago
no, normals get saved nevermind, your fix did nothing because of a mistake in my area of the code pain
Sinan
SinanOP16mo ago
Oh lmao May I ask what it was?
IMS
IMS16mo ago
the line you commented out was to give normals to a vector however, iris didn't know you commented that out so it was just giving empty data and nuking whatever existed before
Sinan
SinanOP16mo ago
Lol How does Iris decide that on it's own? Is that the custom system?
IMS
IMS16mo ago
yep, see the code right below it packs the normals into an integer, regardless of the fact you commented the thing that gives the normals so it was just packing 0, and replacing the right values with 0
Sinan
SinanOP16mo ago
Oh wait, it was completely my fault, now I see it xD
IMS
IMS16mo ago
try this one
Sinan
SinanOP16mo ago
Interesting?
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Rethinking voxels (BSL also does a great job)
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Kappa Despite that, let me try to load metallics So basically the Tangents are still calculated for a flat normal
IMS
IMS16mo ago
lemme see
Sinan
SinanOP16mo ago
Maybe Kappa relies only on tangents
IMS
IMS16mo ago
hm...
Sinan
SinanOP16mo ago
Whcihc makes sense cause kappas shading was the only one that was completely flat in the beginning
IMS
IMS16mo ago
i can make some code quick to make the tangents work with your normals
Sinan
SinanOP16mo ago
That would be awesome! I can also give it a shot but you will be 1000x faster and 1000x more accurate
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Juup, BSL does excellent with the new normals :D IT'S SO BEAUTIFUL
IMS
IMS16mo ago
IMS
IMS16mo ago
(i know it's the same file name; trust me it's different :ioa:)
Sinan
SinanOP16mo ago
Hahahaha Hm, still the same flat tangents Can I please have a look into your new codesnippet? Just to also learn from that
IMS
IMS16mo ago
packedNormal = buffer.getInt(nextElementByte - normalOffset);
tangent = NormalHelper.computeTangent(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal), polygon);
packedNormal = buffer.getInt(nextElementByte - normalOffset);
tangent = NormalHelper.computeTangent(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal), polygon);
Sinan
SinanOP16mo ago
So it's one tangent being passed
IMS
IMS16mo ago
basically instead of computing a normal, i steal it from whatever was put in the original bufferbuilder yes not per-vertex per triangle
Sinan
SinanOP16mo ago
I believe we need 3 per-vertex Or do we? Idk Otherwise the shader can't interpolate
IMS
IMS16mo ago
you probably do, honestly... that's pretty expensive i can probably do that just for the triangle code path though
Sinan
SinanOP16mo ago
Yes that would be awesome 😍
IMS
IMS16mo ago
for (int vertex = 0; vertex < vertexAmount; vertex++) {
int packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
int tangent = NormalHelper.computeTangent(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal), polygon);
buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU);
buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV);
buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent);
}
for (int vertex = 0; vertex < vertexAmount; vertex++) {
int packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
int tangent = NormalHelper.computeTangent(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal), polygon);
buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU);
buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV);
buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent);
}
Sinan
SinanOP16mo ago
Thanks :)) It's still flat Both in kappa and supertester
IMS
IMS16mo ago
then it's probably a flaw with the tangent calculation itself which i am way too dumb to understand
IMS
IMS16mo ago
ok @Sinan i found out it is impossible to calculate a spherical tangent using the normal tangent calculation you must use a separate equation which minecraft doesn't have so... it's not really possible kappa probably needs to just find a way to make it smooth, i can send you the discord of the kappa dev if you want (though they're not too active)
Sinan
SinanOP16mo ago
Yes please! I was looking for it but didn't find it, nor github
Sinan
SinanOP16mo ago
How is that?
IMS
IMS16mo ago
the normal tangent calculation relies on the concept that a triangle can have it's tangent calculated using the 3 points + the UV's when it's a sphere, it doesn't understand that it curves and that falls apart somehow idk
Sinan
SinanOP16mo ago
What separate equation is needed?
IMS
IMS16mo ago
i honestly don't know i'm just going off a forum thread
Sinan
SinanOP16mo ago
Can you please share it?
IMS
IMS16mo ago
Khronos Forums
Sphere tangents
Hi, i hope is the right section. I need to know how to compute sphere tangents. For the normals i saw i can approximate them with vertices coordinates. But for tangents i don’t find nothing. I did this: Vec3s triangle = shape.triangle.at(k); Vec3f vertex1 = shape.vertex.at(triangle[0]); Vec3f vertex2 = shape.vertex.at(triangle[1]); V...
Sinan
SinanOP16mo ago
I am trying to investigate, it must be possible somehow Thank you very much! Just give me a second, I am trying to understand I see, basically one is getting the triange in 2D space first (in UV texture space, that's the difference, just to get the relative triangle as vectors)
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Sinan
SinanOP16mo ago
Game Development Stack Exchange
How to compute tangent and bitangent vectors
I have a texture loaded in three.js, then passed to the shaders. In the vertex shader I compute the normal, and I save into a variable the uv vector.
<script id="vertexShader" type="x-shader/x-
Sinan
SinanOP16mo ago
I am trying to work out the iris calculations But just to be sure, could you please code a check if the tangents computed are even the same? Something like, if the tangents are roughly equal, print a log so that I can see it Well, only if you want, if you trust the debugshader to interpolate tangents then the check is not needed
IMS
IMS16mo ago
The iris calculations are a direct copy of learnopengl Which explains the exact calculation in their normal mapping page
IMS
IMS16mo ago
LearnOpenGL - Normal Mapping
Learn OpenGL . com provides good and clear modern 3.3+ OpenGL tutorials with clear examples. A great resource to learn modern OpenGL aimed at beginners.
Sinan
SinanOP16mo ago
I believe I have an intuition on how to implement per vertex tangent space Let me work this through mathematically (and let me grab a water lol)
IMS
IMS16mo ago
currently eating dinner, no need to rush
Sinan
SinanOP16mo ago
Ah great! Here it's 5 am lmao So, since I wrote this (excluding eating lol), I had the same idea but just thought more about it to be 100% sure that it's stable and correct, I believe it is.
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
If you take a look at this, the blue plane is so to speak the tangent space. E1 and E2 are the geometric triangle. The tangent space is used to map height maps etc to 3D space via a transformation matrix What the Iris code does it is relies on the information that the normal vector is the geometric normal, which it is not for smooth meshes
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
This is from blender how smooth normals look. You can see that for mulitple vertices in one spot, they point in the same direction, making the transition between edges smooth. All normals inbetween are being lerped by the shader
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
This is for flat shading, each vertex normal is different despite sharing the same spot, they point in the direction of the geometric triangle
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
The black arrow is the geometric normal, the green arrow is our smoothly shaded vertex normal Now, the Iris code builds the T and B vectors to specifically be inside the vectorspace that is being spanned by the geometric triangle (given it uses the poligons) To adapt the Iris code to the smooth shading needs, I project the vertices to be inside my new vectorspan, spanned by the perpendicular to my smooth normal (Hold up I am making a visualization)
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
So, all we are doing is taking the points P0 P1 and P2 (vertices) and slide them along the normal vector direction until we hit the green plane, which is spun by our smooth normal vector! This is easily done by a dot product and a recriprocal squareroot and some translations Basically, we do project the point vector onto the normal vector, take the difference of the projected vector and the normal vector and then offset the polygon by that amount And I (why I was holding back with this before) wondered if this may stretch the tangents in a way that would offset the UVs not as wanted. But no, it does not, it should work perfectly fine, because we do that for every vertex! The shader is lerping between those point tangent spaces, so in the end, point to point, the tangent spaces and UVs will easily line up and result in an accurate tangent space computation for smooth meshes. This is pseudo code:
Vector3f normal = new Vector3f(normalX, normalY, normalZ);
Vector3f v0 = new Vector3f(t.x(0), t.y(0), t.z(0));
Vector3f v1 = new Vector3f(t.x(1), t.y(1), t.z(1));
Vector3f v2 = new Vector3f(t.x(2), t.y(2), t.z(2));

float d0 = v0.dot(normal);
v0.sub(normal.mul(d0));

float d1 = v1.dot(normal); // project v1 onto normal
v1.sub(normal.mul(d1)); // offset v1 by the projection to get the point on the plane

float d2 = v2.dot(normal); // project v2 onto normal
v2.sub(normal.mul(d2)); // offset v2 by the projection to get the point on the plane
Vector3f normal = new Vector3f(normalX, normalY, normalZ);
Vector3f v0 = new Vector3f(t.x(0), t.y(0), t.z(0));
Vector3f v1 = new Vector3f(t.x(1), t.y(1), t.z(1));
Vector3f v2 = new Vector3f(t.x(2), t.y(2), t.z(2));

float d0 = v0.dot(normal);
v0.sub(normal.mul(d0));

float d1 = v1.dot(normal); // project v1 onto normal
v1.sub(normal.mul(d1)); // offset v1 by the projection to get the point on the plane

float d2 = v2.dot(normal); // project v2 onto normal
v2.sub(normal.mul(d2)); // offset v2 by the projection to get the point on the plane
And this is the actual change in computeTangent, let's hope I did not make an error: (hold up I will write it somewhat efficient)
IMS
IMS16mo ago
why is it pseudocode? That looks valid
Sinan
SinanOP16mo ago
I do not wanna rely on Vector3f, will do everything component wise
IMS
IMS16mo ago
fair Probably still not as efficient as last one, so I’ll leave it for triangles specifically
Sinan
SinanOP16mo ago
Actually it's 18 multiplications and 9 subtractions more No more than that, should be as efficient, but yes Id also say only for triangles
public static int computeTangent(float normalX, float normalY, float normalZ, TriView t) {
// Project all vertices onto normal plane (for smooth normal support). Optionally skip this step for flat shading.
// Procedure:
// project v onto normal
// offset v by the projection to get the point on the plane

// Capture all of the relevant vertex positions
float x0 = t.x(0);
float y0 = t.y(0);
float z0 = t.z(0);

float x1 = t.x(1);
float y1 = t.y(1);
float z1 = t.z(1);

float x2 = t.x(2);
float y2 = t.y(2);
float z2 = t.z(2);

// project x0, y0, z0 onto normal
float d0 = x0 * normalX + y0 * normalY + z0 * normalZ;
float d1 = x1 * normalX + y1 * normalY + z1 * normalZ;
float d2 = x2 * normalX + y2 * normalY + z2 * normalZ;

// offset x0, y0, z0 by the projection to get the point on the plane
x0 -= d0 * normalX;
y0 -= d0 * normalY;
z0 -= d0 * normalZ;

x1 -= d1 * normalX;
y1 -= d1 * normalY;
z1 -= d1 * normalZ;

x2 -= d2 * normalX;
y2 -= d2 * normalY;
z2 -= d2 * normalZ;


float edge1x = x1 - x0;
float edge1y = y1 - y0;
float edge1z = z1 - z0;
/// [...]
public static int computeTangent(float normalX, float normalY, float normalZ, TriView t) {
// Project all vertices onto normal plane (for smooth normal support). Optionally skip this step for flat shading.
// Procedure:
// project v onto normal
// offset v by the projection to get the point on the plane

// Capture all of the relevant vertex positions
float x0 = t.x(0);
float y0 = t.y(0);
float z0 = t.z(0);

float x1 = t.x(1);
float y1 = t.y(1);
float z1 = t.z(1);

float x2 = t.x(2);
float y2 = t.y(2);
float z2 = t.z(2);

// project x0, y0, z0 onto normal
float d0 = x0 * normalX + y0 * normalY + z0 * normalZ;
float d1 = x1 * normalX + y1 * normalY + z1 * normalZ;
float d2 = x2 * normalX + y2 * normalY + z2 * normalZ;

// offset x0, y0, z0 by the projection to get the point on the plane
x0 -= d0 * normalX;
y0 -= d0 * normalY;
z0 -= d0 * normalZ;

x1 -= d1 * normalX;
y1 -= d1 * normalY;
z1 -= d1 * normalZ;

x2 -= d2 * normalX;
y2 -= d2 * normalY;
z2 -= d2 * normalZ;


float edge1x = x1 - x0;
float edge1y = y1 - y0;
float edge1z = z1 - z0;
/// [...]
That should be it Let's hope it works, it's 6 AM and I didn't have lots of sleep last night either, so let's see haha
IMS
IMS16mo ago
time to see
Sinan
SinanOP16mo ago
Efficiency wise, if d0, d1 and d2 are basically 0, we can skip the whole offset part :nervousIntensifies:
IMS
IMS16mo ago
i'm replacing all usages for the test
Sinan
SinanOP16mo ago
Which test usages?
IMS
IMS16mo ago
i mean i'm replacing terrain and all
Sinan
SinanOP16mo ago
Ah right!
Sinan
SinanOP16mo ago
Blazing fast How do you do that
IMS
IMS16mo ago
building takes less than 5 seconds on our toolchain lol
Sinan
SinanOP16mo ago
still, you got like 50 words a sec lol OK SO
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
ALMOST This is Kappa btw Let me check the other shaders Ok, interestingly the supertester still shows flat tangents, that doesn't make a whole lot of sense, but well
IMS
IMS16mo ago
wait should i have put in the change that makes the tangents per vertex i reverted it
Sinan
SinanOP16mo ago
Yes please calculateTangent per vertex and keep the smooth normals
IMS
IMS16mo ago
👍 @Sinan
Sinan
SinanOP16mo ago
Huh, that's very interesting
IMS
IMS16mo ago
wait i think i got the code wrong it's grabbing the same normal 3 times instead of grabbing the 3 normals
Sinan
SinanOP16mo ago
Ah alright :D
Sinan
SinanOP16mo ago
Was that the same behaviour in the beginning?
IMS
IMS16mo ago
yes i think maybe i don't know
Sinan
SinanOP16mo ago
Let's see :)
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Hmm
IMS
IMS16mo ago
good enough™️
Sinan
SinanOP16mo ago
xD
IMS
IMS16mo ago
how does the flat mirror look
Sinan
SinanOP16mo ago
Idk why it's still flat
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
It looks like it's still only fetching the tangent from one vertex Let me try something
IMS
IMS16mo ago
for (int vertex = 0; vertex < vertexAmount; vertex++) {
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
int tangent = NormalHelper.computeTangent(Norm3b.unpackX(packedNormal), Norm3b.unpackY(packedNormal), Norm3b.unpackZ(packedNormal), polygon);
buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU);
buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV);
buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent);
}
for (int vertex = 0; vertex < vertexAmount; vertex++) {
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
int tangent = NormalHelper.computeTangent(Norm3b.unpackX(packedNormal), Norm3b.unpackY(packedNormal), Norm3b.unpackZ(packedNormal), polygon);
buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU);
buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV);
buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent);
}
Sinan
SinanOP16mo ago
Is that the latest code I got?
IMS
IMS16mo ago
yep
Sinan
SinanOP16mo ago
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
I dont understand much about that (what is stride) but it seems to be fine
IMS
IMS16mo ago
and the addition to computeTangent
No description
IMS
IMS16mo ago
the size of a vertex so it's basically displacing by the amount of bytes in a vertex
Sinan
SinanOP16mo ago
Ah okay Argh idk why it's doing that, being flat I just loaded an old iris and it looks exactly the same
IMS
IMS16mo ago
i think it's up to rre (the creator of kappa) to try to smooth out tangents prob
Sinan
SinanOP16mo ago
Which leads me to believe, does kappa not interpolate tangent?
IMS
IMS16mo ago
maybe not? i know there were similar problems at some point lemme go through the backlog
Sinan
SinanOP16mo ago
Yeah, but why is supertester not working But take a look at this
IMS
IMS16mo ago
if you mean across triangles no
Sinan
SinanOP16mo ago
Supertester:
IMS
IMS16mo ago
you cannot interpolate across triangles, that's not possible
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Flat mirror is at least flat
IMS
IMS16mo ago
yeah, with the flat mirror i'm pretty sure something's wrong in kappa with the sphere the tangents are pretty obviously pixelated
Sinan
SinanOP16mo ago
This is BSL (before the iris tangent recalculation, BSL ignores tangents alltogether)
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
bsl can't ignore tangents, though? time to grab bsl and see the code
Sinan
SinanOP16mo ago
Ah Im sorry, I mean at least it doesn't base it's normalmapping offof it Yayyy
IMS
IMS16mo ago
but that's... a critical part of normal mapping you get extremely scuffed normal mapping without it
Sinan
SinanOP16mo ago
Can we test setting the tangent to a fixed value? Some random vector that's the same for all vertices?
IMS
IMS16mo ago
ok yeah tangent is definitely used in BSL sure what value?
Sinan
SinanOP16mo ago
1,0,0 Or something
IMS
IMS16mo ago
w value? (if you know what that does :ioa:) it's just that BSL constructs everything into a TBN matrix
Sinan
SinanOP16mo ago
oh sry also 0
IMS
IMS16mo ago
before messign with it
Sinan
SinanOP16mo ago
But it uses the T for it right?
IMS
IMS16mo ago
the B is T cross N iirc
Sinan
SinanOP16mo ago
Yes, but why does BSL work I guess we will see with a fixed tangent value
IMS
IMS16mo ago
IMS
IMS16mo ago
@RRe36 can probably look at this in the morning, idk (bsl has a perfect mirror made out of triangles, but kappa has problems with shading seemingly due to interpolation, see photos above) the normals are smooth shaded but the tangents are flat shaded due to being calculated on the fly
Sinan
SinanOP16mo ago
Apparently, Kappa does not care about smooth per-vertex normals and perhaps bases it's own normal (not normal map, just displayed normals) on the tangent vector space rather than on interpolating between the vertex normals, other shaders like BSL or Complementary do also take the tangent into account but somehow are able to smoothly interpolate between normals despite wrong per-vertex tangent spaces
IMS
IMS16mo ago
wait i think i remember some option for this in shader settings go to terrain and flip on vertex attribute fix see if that does anything i think it was for entities only though
Sinan
SinanOP16mo ago
Is that the new fixed value tangent? Somehow in the shaders it looks exactly the same, only in supertester it shows me the fixed val I am using the entity solid and entity vertex provider I tried the vertex attribute fix, when I toggle it on, it makes the mesh render flat
IMS
IMS16mo ago
if supertester shows it it's the real value
Sinan
SinanOP16mo ago
Yes, supertester shows the real value, Kappa looks exactly the same with the fixed tangent But BSL breaks
IMS
IMS16mo ago
that's a problem, but it's likely not the problem here but it's probably related in some form the tl;dr is long ago (3 years ago) optifine was notorious for providing just completely screwed normal and tangent values on entities so shaderpacks made fixes in the form of calculating their own
Sinan
SinanOP16mo ago
I didn't know what to do, should I switch to solid in genereal? Can I then expect rethinking voxel shadows etc?
IMS
IMS16mo ago
some shaderpacks just kept it that way ever since, even when it was fixed i don't mean it's a problem with your renderer
Sinan
SinanOP16mo ago
I totally see...
IMS
IMS16mo ago
it's just a historical problem with entities and normal mapping that shaders worked around and now the workaround breaks things i can't say if that's what's happening here
Sinan
SinanOP16mo ago
Just for the record
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
BSL with fixed tangent space
IMS
IMS16mo ago
yep, that's tangents being screwed exactly what i'd expect if kappa is not as screwed that indicates it's making it's own TBN
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Kappa with fixed tangent space Notice that now that it's facing in one world space axis (I suppose), the mirror is flat and from the other side the sphere works (as a flat mirror) For completeness sake:
IMS
IMS16mo ago
i found the code in kappa that makes it's own tbn
Sinan
SinanOP16mo ago
No description
IMS
IMS16mo ago
mat3 manualTBN(vec3 pos, vec2 uv) {

uv *= textureSize(normals, 0);

vec3 deltaPos1 = dFdx(pos);
vec3 deltaPos2 = dFdy(pos);
vec2 deltaUV1 = dFdx(uv);
vec2 deltaUV2 = dFdy(uv);

vec3 deltaPos1Perp = cross(normal, deltaPos1);
vec3 deltaPos2Perp = cross(deltaPos2, normal);

vec3 tangent = normalize(deltaPos2Perp * deltaUV1.x + deltaPos1Perp * deltaUV2.x);
vec3 bitangent = normalize(deltaPos2Perp * deltaUV1.y + deltaPos1Perp * deltaUV2.y);

return mat3(tangent.x, bitangent.x, normal.x,
tangent.y, bitangent.y, normal.y,
tangent.z, bitangent.z, normal.z);
}
mat3 manualTBN(vec3 pos, vec2 uv) {

uv *= textureSize(normals, 0);

vec3 deltaPos1 = dFdx(pos);
vec3 deltaPos2 = dFdy(pos);
vec2 deltaUV1 = dFdx(uv);
vec2 deltaUV2 = dFdy(uv);

vec3 deltaPos1Perp = cross(normal, deltaPos1);
vec3 deltaPos2Perp = cross(deltaPos2, normal);

vec3 tangent = normalize(deltaPos2Perp * deltaUV1.x + deltaPos1Perp * deltaUV2.x);
vec3 bitangent = normalize(deltaPos2Perp * deltaUV1.y + deltaPos1Perp * deltaUV2.y);

return mat3(tangent.x, bitangent.x, normal.x,
tangent.y, bitangent.y, normal.y,
tangent.z, bitangent.z, normal.z);
}
Sinan
SinanOP16mo ago
(same from all angles)
IMS
IMS16mo ago
this is the code in kappa but it should be off unless tbnFix is on which is activated by vertex attribute fix
Sinan
SinanOP16mo ago
That makes sense, rendering everything flat Can you please test something?
IMS
IMS16mo ago
sure
Sinan
SinanOP16mo ago
I wanna make sure that even supertester interpolates the tangent space
IMS
IMS16mo ago
supertester does the bare minimum debug = tangent * 0.5 + 0.5; where tangent = normalize(at_tangent.xyz) interpolated across the triangle
Sinan
SinanOP16mo ago
Could you please set the tangent space matrix to be a randomized Oh really, hm
IMS
IMS16mo ago
normalmatrix? that will probably screw with much more than you want including the game visual itself
Sinan
SinanOP16mo ago
By sending random tangent spaces per vertex?
IMS
IMS16mo ago
the normalmatrix is the model view matrix inverted and transposed
Sinan
SinanOP16mo ago
For simplicity, randomly decide between 1,0,0,0 and 0,1,0,0
IMS
IMS16mo ago
it's used in calculations outside normals ok
Sinan
SinanOP16mo ago
No that's not what I meant
IMS
IMS16mo ago
you want every other vertex or completely random?
Sinan
SinanOP16mo ago
I meant the tangent space output to be nrormalized completely random But 1,0,0,0 and 0,1,0,0 should at least give some info These are very bad tangent space values, as in they will project everything into 1d space, but meh it's about seing if interpolation works
IMS
IMS16mo ago
this should do it
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Yuuup, interpolation works
Sinan
SinanOP16mo ago
This is the old nonfixed tangent space code
No description
Sinan
SinanOP16mo ago
It does do interpolation Which could explain why BSL etc is seemingly working
IMS
IMS16mo ago
going to sleep soon, tell me if you have something else for me to try
Sinan
SinanOP16mo ago
I am out of ideas on what we could test on the Iris side... I wish you a good night and thank you for your awesome help!
IMS
IMS16mo ago
no problem! i can help more tomorrow if needed
Sinan
SinanOP16mo ago
(I hope you disabled notifications before going to bed) I think the tangent fix we did works beautifully, the picture below shows flat tangents, compare them to the tangents I sent above and it looks correctly interpolated
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Which explains why the other shaders work flawlessly @RRe36 Hey, I just worked with hedge hog on implementing per vertex tangent space, I modified it by simply projecting the vertices on the smooth normal plane instead of the geometric normal, which supposedly works BSL and Complementary shaders now support smooth mesh shading:
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
But Kappa (which I totally LOVE, I have never seen a shader like it, true metallics, reflection probes and just all post processing effects one would ever want with the highes quality, JUST A DREAM COME TRUE) does this:
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Perhaps Kappa is only using the tangent space of one vertex and using that for all 3 vertices? That would explain the "broken" mirror
kristal (she) | pegasys
@IMS wouldn't it be wise to ask for a forum channel in slabs for developing shaders for iris?
Sinan
SinanOP16mo ago
@IMS Hey! :) I wanted to ask, what did you do to the packing normals to 0, did you just remove the line to make smooth normals work? I am preparing the tangent space per-vertex PR (I wrote it with an argument overload boolean so that only on tris this gets executed, only in the right place the boolean overload gets called. This way it's maximum efficiency, it's only 19 mults and 8 additions overall only for tris.)
IMS
IMS16mo ago
what do you mean by doing the packing normals to 0? to get the packed normal buffer.getInt(nextElementByte - normalOffset - stride * vertex) to unpack it
public static float unpackX(int norm) {
return (float)((byte)(norm & 255)) * 0.007874016F;
}

public static float unpackY(int norm) {
return (float)((byte)(norm >> 8 & 255)) * 0.007874016F;
}

public static float unpackZ(int norm) {
return (float)((byte)(norm >> 16 & 255)) * 0.007874016F;
}
public static float unpackX(int norm) {
return (float)((byte)(norm & 255)) * 0.007874016F;
}

public static float unpackY(int norm) {
return (float)((byte)(norm >> 8 & 255)) * 0.007874016F;
}

public static float unpackZ(int norm) {
return (float)((byte)(norm >> 16 & 255)) * 0.007874016F;
}
Sinan
SinanOP16mo ago
packedNormal = NormalHelper.packNormal(normal, 0.0f); The code calls this after the comment out of the tri normal recalculation
IMS
IMS16mo ago
yeah, I had to change that put that in the quad only code
Sinan
SinanOP16mo ago
Ok I would place that where the line I sent was for tris only right?
IMS
IMS16mo ago
and where the tri normal recalculation took place, do this packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
Sinan
SinanOP16mo ago
Okay nice sure :) I am so glad that it all worked out beautifully! I am excited to know where the Issue with Kappa lies, after solving that, Iris has full support for custom smooth meshes! :blush_AE:
int packedNormal = -1;
if (vertexAmount == 3) {
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
// Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent.
// NormalHelper.computeFaceNormalTri(normal, polygon);
} else {
NormalHelper.computeFaceNormal(normal, polygon);
packedNormal = NormalHelper.packNormal(normal, 0.0f);
}

int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon, vertexAmount == 3);
int packedNormal = -1;
if (vertexAmount == 3) {
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
// Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent.
// NormalHelper.computeFaceNormalTri(normal, polygon);
} else {
NormalHelper.computeFaceNormal(normal, polygon);
packedNormal = NormalHelper.packNormal(normal, 0.0f);
}

int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon, vertexAmount == 3);
// disabled by default
public static int computeTangent(float normalX, float normalY, float normalZ, TriView t) {
returm computeTangent(normalX, normalY, normalZ, t, false);
}

public static int computeTangent(float normalX, float normalY, float normalZ, TriView t, boolean smoothNormals) {
// disabled by default
public static int computeTangent(float normalX, float normalY, float normalZ, TriView t) {
returm computeTangent(normalX, normalY, normalZ, t, false);
}

public static int computeTangent(float normalX, float normalY, float normalZ, TriView t, boolean smoothNormals) {
Does that look fine to you? Oh and also, does Iris have an API call event for when the shaders are done being reloaded?
IMS
IMS16mo ago
sadly, no no, since normal isn't computed by packedNormal so you need to unpack it using my unpack function
Sinan
SinanOP16mo ago
Ah of course!
int packedNormal = -1;
if (vertexAmount == 3) {
// Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent.
// NormalHelper.computeFaceNormalTri(normal, polygon);
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
normal = new Vector3f(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal));
} else {
NormalHelper.computeFaceNormal(normal, polygon);
packedNormal = NormalHelper.packNormal(normal, 0.0f);
}
int packedNormal = -1;
if (vertexAmount == 3) {
// Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent.
// NormalHelper.computeFaceNormalTri(normal, polygon);
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
normal = new Vector3f(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal));
} else {
NormalHelper.computeFaceNormal(normal, polygon);
packedNormal = NormalHelper.packNormal(normal, 0.0f);
}
Now okay?
IMS
IMS16mo ago
that works though it'll certainly not be fast lol this actually doesn't really matter because Sodium codepaths don't use BufferBuilder and use a faster alternative
Sinan
SinanOP16mo ago
In what sense?
IMS
IMS16mo ago
this is per-quad anything you do gets multiplied hundreds of thousands as much so everything is expensive
Sinan
SinanOP16mo ago
You mean packedNormal = NormalHelper.packNormal(normal, 0.0f);? It was like this before, just for all quads and tris, right? https://github.com/IrisShaders/Iris/blob/168599f79a6877ee27c296f22fba126612940a09/src/main/java/net/coderbot/iris/mixin/vertices/MixinBufferBuilder.java#L253
IMS
IMS16mo ago
it's probably fine honestly don't worry replace normal = new Vector3f with normal.set because fun fact; creating a new object is horrendously expensive which is why it's always avoided in hot paths
Sinan
SinanOP16mo ago
Ah okay!
int packedNormal = -1;
if (vertexAmount == 3) {
// Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent.
// NormalHelper.computeFaceNormalTri(normal, polygon);
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
normal.set(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal));
} else {
NormalHelper.computeFaceNormal(normal, polygon);
packedNormal = NormalHelper.packNormal(normal, 0.0f);
}

int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon, vertexAmount == 3);
int packedNormal = -1;
if (vertexAmount == 3) {
// Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent.
// NormalHelper.computeFaceNormalTri(normal, polygon);
packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex);
normal.set(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal));
} else {
NormalHelper.computeFaceNormal(normal, polygon);
packedNormal = NormalHelper.packNormal(normal, 0.0f);
}

int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon, vertexAmount == 3);
IMS
IMS16mo ago
looks ok
Sinan
SinanOP16mo ago
I don't quite get, why would that be expensive and per quad?
IMS
IMS16mo ago
per-primitive i mean not per-quad so triangle, quad, whatever you're using
Sinan
SinanOP16mo ago
I still don't get what I introduced that did more operations per primitive
IMS
IMS16mo ago
basically, everything you do in BufferBuilder needs to be aggressively optimized otherwise your performance dies the unpack functions are more operations but like i said, it's unavoidable so it's fine
Sinan
SinanOP16mo ago
Oh okay, but that's just for tris now right?
IMS
IMS16mo ago
only if if() wasn't expensive too :Waaa: but yeah it's fine
Sinan
SinanOP16mo ago
Ohhh, you mean the vertexAmount == 3 in the computeTangent Hold up
IMS
IMS16mo ago
just make a new computeTangentSmooth
Sinan
SinanOP16mo ago
Yeah I wanted to do that
IMS
IMS16mo ago
and use that in the if vertexAmount == 3
Sinan
SinanOP16mo ago
:) Okay! Wait, I think this is missing from my code Let me try to write something efficient with as less ifs as possible Is a new for loop introducing any overhead? I would do a per-vertex for loop inside the if(vertexAmount == 3), storing the tangents in an array (and fill the array with all same quad data otherwise)
IMS
IMS16mo ago
Why not just move the last for loop into the if statement? and duplicate it
Sinan
SinanOP16mo ago
Oh sure!
@Unique
private void fillExtendedData(int vertexAmount) {
vertexCount = 0;

int stride = format.getVertexSize();

polygon.setup(buffer, nextElementByte, stride, vertexAmount);

float midU = 0;
float midV = 0;

for (int vertex = 0; vertex < vertexAmount; vertex++) {
midU += polygon.u(vertex);
midV += polygon.v(vertex);
}

midU /= vertexAmount;
midV /= vertexAmount;

int midUOffset;
int midVOffset;
int normalOffset;
int tangentOffset;
if (iris$isTerrain) {
midUOffset = 16;
midVOffset = 12;
normalOffset = 24;
tangentOffset = 8;
} else {
midUOffset = 14;
midVOffset = 10;
normalOffset = 24;
tangentOffset = 6;
}

if (vertexAmount == 3) {
// NormalHelper.computeFaceNormalTri(normal, polygon); // Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent.

for (int vertex = 0; vertex < vertexAmount; vertex++) {
int packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex); // retrieve per-vertex normal
normal.set(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal));

int tangent = NormalHelper.computeTangentSmooth(normal.x, normal.y, normal.z, polygon);

buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU);
buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV);
buffer.putInt(nextElementByte - normalOffset - stride * vertex, packedNormal);
buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent);
}
} else {
NormalHelper.computeFaceNormal(normal, polygon);
int packedNormal = NormalHelper.packNormal(normal, 0.0f);
int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon);

for (int vertex = 0; vertex < vertexAmount; vertex++) {
buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU);
buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV);
buffer.putInt(nextElementByte - normalOffset - stride * vertex, packedNormal);
buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent);
}
}
}
@Unique
private void fillExtendedData(int vertexAmount) {
vertexCount = 0;

int stride = format.getVertexSize();

polygon.setup(buffer, nextElementByte, stride, vertexAmount);

float midU = 0;
float midV = 0;

for (int vertex = 0; vertex < vertexAmount; vertex++) {
midU += polygon.u(vertex);
midV += polygon.v(vertex);
}

midU /= vertexAmount;
midV /= vertexAmount;

int midUOffset;
int midVOffset;
int normalOffset;
int tangentOffset;
if (iris$isTerrain) {
midUOffset = 16;
midVOffset = 12;
normalOffset = 24;
tangentOffset = 8;
} else {
midUOffset = 14;
midVOffset = 10;
normalOffset = 24;
tangentOffset = 6;
}

if (vertexAmount == 3) {
// NormalHelper.computeFaceNormalTri(normal, polygon); // Removed to enable smooth shaded triangles. Mods rendering triangles with bad normals need to recalculate their normals manually or otherwise shading might be inconsistent.

for (int vertex = 0; vertex < vertexAmount; vertex++) {
int packedNormal = buffer.getInt(nextElementByte - normalOffset - stride * vertex); // retrieve per-vertex normal
normal.set(unpackX(packedNormal), unpackY(packedNormal), unpackZ(packedNormal));

int tangent = NormalHelper.computeTangentSmooth(normal.x, normal.y, normal.z, polygon);

buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU);
buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV);
buffer.putInt(nextElementByte - normalOffset - stride * vertex, packedNormal);
buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent);
}
} else {
NormalHelper.computeFaceNormal(normal, polygon);
int packedNormal = NormalHelper.packNormal(normal, 0.0f);
int tangent = NormalHelper.computeTangent(normal.x, normal.y, normal.z, polygon);

for (int vertex = 0; vertex < vertexAmount; vertex++) {
buffer.putFloat(nextElementByte - midUOffset - stride * vertex, midU);
buffer.putFloat(nextElementByte - midVOffset - stride * vertex, midV);
buffer.putInt(nextElementByte - normalOffset - stride * vertex, packedNormal);
buffer.putInt(nextElementByte - tangentOffset - stride * vertex, tangent);
}
}
}
Does this look fast? Lol
IMS
IMS16mo ago
You can remove the putInt for packed normal on tris because it’ll always be identical otherwise yeah, it looks good
Sinan
SinanOP16mo ago
What do you mean? Doesn't this then remove the smooth normals?
IMS
IMS16mo ago
you’re doing buffer.putInt on packedNormal but packedNormal is retrieved from buffer.getInt
Sinan
SinanOP16mo ago
Ohhh, I see! Shall I remove the line or comment it out?
IMS
IMS16mo ago
Remove it since it’s in the quad path
Sinan
SinanOP16mo ago
Ok great, I did the PR!
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Wait I did something wrong Oh these were not in the code... @IMS Should I add the functions to MixinBufferBuilder or use normalX = Norm3b.unpackX(normal); normalY = Norm3b.unpackY(normal); normalZ = Norm3b.unpackZ(normal); These?
import me.jellysquid.mods.sodium.client.util.Norm3b;
IMS
IMS16mo ago
Don’t use those They’re from sodium, so if you launch the game without sodium it’ll crash
Sinan
SinanOP16mo ago
Ah right, I am dumb ill add em to normalhelper Sorry, now the checks check out :flooshed: Committed it Okay, the whole custom mesh rendering journey is almost over There is just one thing to do, I discovered UV mapping issues, but I think it's closely related to the shaders ways of using the tangent space
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
In this screenshot with Kappa (so, don't mind the flat rendering despite the mesh being flat), the specular map maps perfectly fine (hold up, I need to construct a new texture) However, in BSL the specular mapping is all over the place
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
That's the whole issue. Now here is some side info: When I enable parallax occlusion mapping, every shader messes up all of my UVs. Take a look:
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
With Parallax occlusion mapping all (c, s, n) textures get displaced in the same pattern as only the s texture without parallax occlusion in BSL only
IMS
IMS16mo ago
:agony:
Sinan
SinanOP16mo ago
Id' say if we fix the POM issue in general, the specular map will fix itself in BSL :Sob_AE:
IMS
IMS16mo ago
i don't know what that could possibly be if the tangents are right
Sinan
SinanOP16mo ago
I sadly can not enable parallax occlusion mapping in supertester
IMS
IMS16mo ago
i rewrote a lot of your PR and merged it https://github.com/IrisShaders/Iris/commit/9b04558f60538e5523031bf4696f38d7a8587441 (it now uses a dedicated NormI8 class to handle normal packs)
Sinan
SinanOP16mo ago
Oh awesome, thank you! :) I wanted to ask, is there an API or event that I can register to rebake my meshes on switching from shadern on vs off? I also wanted to ask, which of those shaders gets used when I draw with the ENTITY_SOLID_PROGRAM aka getRenderTypeEntitySolidProgram()
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Is it the gbuffers_entity.glsl? I just wanna know to look into the code and POM implementations
IMS
IMS16mo ago
Yep
Sinan
SinanOP16mo ago
No description
Sinan
SinanOP16mo ago
Yay I modded Kappa :D was a simple removal of flat for normal and tbn
Ultimate Immersion
This is epic, I was looking for something like this for ages.
Want results from more Discord servers?
Add your server