by illYay1337 » Sat Nov 19, 2022 12:29 pm
My account works again so I'm able to post here. Made the original post here just now but I'm sure this is a better thread to ask questions.
https://www.doomworld.com/forum/topic/1 ... m-shaders/
I normally consider myself somewhat of an expert with GLSL and computer graphics so I was able to piece together how to make a custom shader in GZDoom after poking around.
Basically I'm running into issues where surfaces that have a shader applied seem brighter and are lit differently than surfaces without shaders.
Here the walls that are not at 90 degree angles are really showing the effect. The darker walls are the non-shader version. The 90 degree walls on the right have no issues, which I'm guessing is because it's in the default shading mode on this map right now.
Spoiler:
Here the surfaces with my shader are flat shaded instead of using sector lighting, which actually makes things look a bit uglier. Seems like we don't have access to the vertex shader and I'm not really sure how to even do smooth shading in Doom with normal geometry short of using a 3D model. I'd rather it actually used sector lighting so I just get the shader effect.
Spoiler:
Also surfaces with a shader exhibit this pinprick effect, which is especially visible on slopes. It's easier to see against a solid color with a super simple shader that outputs red.
Spoiler:
The shader code itself, which I think I'll post in the shaders section later once I think it's fully ready.
Spoiler:
Code: Select all
/**
* Shader that does triplanar mapping which should be great for natural terrain textures
* The UVs are procedurally determined based on world coordinates so caves, mountains, etc automatically look good
* This can be very useful for Doom where it's otherwise difficult or nearly impossible to align walls and flats
* At the moment it's built to take the passed in texture and triplanar map it.
*
* Made with the help of this article: https://www.martinpalko.com/triplanar-mapping/#The%20Theory
*
* Future versions or variations might get more advanced, and you could make snowy mountains for example, by having top facing normals use a snow texture
*
* Usage: Add to gldefs as explained here: https://zdoom.org/wiki/GLDEFS
*
* You can add either a worldScale define or uvScale define
* By default it acts as if you passed worldScale 1.0
* worldScale 1.0 will try to map the texture as closely to how doom would map it as possible in doom's world coordinates
* Other values will multiply the scale
*
* uvScale won't take world scale into account and will just base UV's one to one with world position, so you may want very low values like .001 to look good.
* uvScale is slightly more optimized since there's no division by texture size
*
* e.g.
* material texture "textures/ogrodtex/OGRIDRST_triplanar.png"
* {
* shader "shaders/triplanar.fp"
* define worldScale = 2
* }
*/
Material ProcessMaterial()
{
Material material;
vec2 uvScaleActual =
#ifdef uvScale
vec2(uvScale);
#else
#ifndef worldScale
#define worldScale 1.0
#endif
//to sample the texture in "DooM" world units we divide by its size
1.0 / textureSize(tex, 0) * worldScale;
#endif
vec3 normals = normalize(vWorldNormal.xyz);
vec3 blendWeights = abs(normals);
// Z normal faces north/south
// Y normal faces floor/ceiling or up/down
// X normal faces east/west
// Floor / Ceiling need to sample in the -v direction
// Walls sample in the -v direction as well, but also flip u depending on facing direction to more roughly match doom's texture mapping
vec2 northSouthUVs = pixelpos.xy * vec2(sign(-normals.z), -1.0) * uvScaleActual;
vec2 floorCeilUVs = pixelpos.xz * vec2(1.0, -1.0) * uvScaleActual;
vec2 eastWestUVs = pixelpos.zy * vec2(sign(normals.x), -1.0) * uvScaleActual;
material.Base =
// North / South
getTexel(northSouthUVs) * blendWeights.z
// Floor / Ceiling
+ getTexel(floorCeilUVs) * blendWeights.y
// East / West
+ getTexel(eastWestUVs) * blendWeights.x;
// In the future, if more textures are used for other material components, sample them in a similar way
// Future versions can also sample a totally different texture for Floor, for example, to add snow or grass to tops of hills
// You could also sample different textures based on elevation in world coordinates, so high peaks are snowy while low areas are grassy
return material;
}
My account works again so I'm able to post here. Made the original post here just now but I'm sure this is a better thread to ask questions. https://www.doomworld.com/forum/topic/132535-gzdoom-and-custom-shaders/
I normally consider myself somewhat of an expert with GLSL and computer graphics so I was able to piece together how to make a custom shader in GZDoom after poking around.
Basically I'm running into issues where surfaces that have a shader applied seem brighter and are lit differently than surfaces without shaders.
Here the walls that are not at 90 degree angles are really showing the effect. The darker walls are the non-shader version. The 90 degree walls on the right have no issues, which I'm guessing is because it's in the default shading mode on this map right now.
[spoiler]
[imgur]https://imgur.com/g6sHiS1[/imgur]
[/spoiler]
Here the surfaces with my shader are flat shaded instead of using sector lighting, which actually makes things look a bit uglier. Seems like we don't have access to the vertex shader and I'm not really sure how to even do smooth shading in Doom with normal geometry short of using a 3D model. I'd rather it actually used sector lighting so I just get the shader effect.
[spoiler]
[imgur]https://imgur.com/ctzhzkY[/imgur]
[/spoiler]
Also surfaces with a shader exhibit this pinprick effect, which is especially visible on slopes. It's easier to see against a solid color with a super simple shader that outputs red.
[spoiler]
[imgur]https://imgur.com/acMOJSR[/imgur]
[/spoiler]
The shader code itself, which I think I'll post in the shaders section later once I think it's fully ready.
[spoiler]
[code]/**
* Shader that does triplanar mapping which should be great for natural terrain textures
* The UVs are procedurally determined based on world coordinates so caves, mountains, etc automatically look good
* This can be very useful for Doom where it's otherwise difficult or nearly impossible to align walls and flats
* At the moment it's built to take the passed in texture and triplanar map it.
*
* Made with the help of this article: https://www.martinpalko.com/triplanar-mapping/#The%20Theory
*
* Future versions or variations might get more advanced, and you could make snowy mountains for example, by having top facing normals use a snow texture
*
* Usage: Add to gldefs as explained here: https://zdoom.org/wiki/GLDEFS
*
* You can add either a worldScale define or uvScale define
* By default it acts as if you passed worldScale 1.0
* worldScale 1.0 will try to map the texture as closely to how doom would map it as possible in doom's world coordinates
* Other values will multiply the scale
*
* uvScale won't take world scale into account and will just base UV's one to one with world position, so you may want very low values like .001 to look good.
* uvScale is slightly more optimized since there's no division by texture size
*
* e.g.
* material texture "textures/ogrodtex/OGRIDRST_triplanar.png"
* {
* shader "shaders/triplanar.fp"
* define worldScale = 2
* }
*/
Material ProcessMaterial()
{
Material material;
vec2 uvScaleActual =
#ifdef uvScale
vec2(uvScale);
#else
#ifndef worldScale
#define worldScale 1.0
#endif
//to sample the texture in "DooM" world units we divide by its size
1.0 / textureSize(tex, 0) * worldScale;
#endif
vec3 normals = normalize(vWorldNormal.xyz);
vec3 blendWeights = abs(normals);
// Z normal faces north/south
// Y normal faces floor/ceiling or up/down
// X normal faces east/west
// Floor / Ceiling need to sample in the -v direction
// Walls sample in the -v direction as well, but also flip u depending on facing direction to more roughly match doom's texture mapping
vec2 northSouthUVs = pixelpos.xy * vec2(sign(-normals.z), -1.0) * uvScaleActual;
vec2 floorCeilUVs = pixelpos.xz * vec2(1.0, -1.0) * uvScaleActual;
vec2 eastWestUVs = pixelpos.zy * vec2(sign(normals.x), -1.0) * uvScaleActual;
material.Base =
// North / South
getTexel(northSouthUVs) * blendWeights.z
// Floor / Ceiling
+ getTexel(floorCeilUVs) * blendWeights.y
// East / West
+ getTexel(eastWestUVs) * blendWeights.x;
// In the future, if more textures are used for other material components, sample them in a similar way
// Future versions can also sample a totally different texture for Floor, for example, to add snow or grass to tops of hills
// You could also sample different textures based on elevation in world coordinates, so high peaks are snowy while low areas are grassy
return material;
}[/code]
[/spoiler]