I have a question about normal mapping in directx9 shader.
Currently my Terrain shader Output for Normal Map + Diffuse Color only result into this Image.
Which looks good to me.
If i use an empty Normal map image like this one.
My shader output for normal diffuse and color map looks like this.
But if i use 1 including a ColorMap i get a really stange result.
Does anyone have an idea what could cause this issue?
Here is some snippets.
float4 PS_TERRAIN(VSTERRAIN_OUTPUT In) : COLOR0
{
float4 fDiffuseColor;
float lightIntensity;
float3 bumpMap = 2.0f * tex2D( Samp_Bump, In.Tex.xy ).xyz-1.0f;
float3 bumpNormal = (bumpMap.x * In.Tangent) + (bumpMap.y * In.Bitangent) + (bumpMap.z * In.Normal);
bumpNormal = normalize(bumpNormal);
// Direction Light Test ( Test hardcoded )
float3 lightDirection = float3(0.0f, -0.5f, -0.2f);
float3 lightDir = -lightDirection;
// Bump
lightIntensity = saturate(dot( bumpNormal, lightDir));
// We are using a lightmap to do our alpha calculation for given pixel
float4 LightMaptest = tex2D( Samp_Lightmap, In.Tex.zw ) * 2.0f;
fDiffuseColor.a = LightMaptest.a;
if( !bAlpha )
fDiffuseColor.a = 1.0;
// Sample the pixel color from the texture using the sampler at this texture coordinate location.
float4 textureColor = tex2D( Samp_Diffuse, In.Tex.xy );
// Combine the color map value into the texture color.
textureColor = saturate(textureColor * LightMaptest);
textureColor.a = LightMaptest.a;
fDiffuseColor.rgb = saturate(lightIntensity * I_d).rgb;
fDiffuseColor = fDiffuseColor * textureColor; // If i enable this line it goes crazy
return fDiffuseColor;
}
Related
I'm trying to teach myself the basics of computer graphics on the iPhone and Apple's Metal API. I'm trying to do something pretty basic, but I'm getting a little stuck.
What I want to do is just "texture a quad". Basically, I make a rectangle and I have an image texture that covers the rectangle. I can make that work for the basic case where the image texture just comes from an image of a known format, but I'm having trouble figuring out how to make my code a little more generic and able to handle different formats.
For example, sometimes the image texture comes from an image file, which after decoding it, the pixel data is in the RGB format. Sometimes, my image texture actually comes from a video frame where the data is stored in the YUV format.
Ideally, I'd want to create some sort of "sampler" object or function that can just hand me back an RGB color for a particular texture coordinate. In the code where I prepare for rendering, that's the part with context on which format is getting used, and so it would have enough information to figure out which type of sampler should get used. For example, in the video frame case, it knows that it's working with a video frame and so it creates a YUV sampler and passes it the relevant data. And then from my shader code that just wants to read colors, it can just ask for the color at some particular coordinates, and the YUV sampler would do the proper work to compute the right RGB color. If I passed in an RGB sampler instead, it would just read the RGB data without doing any sort of calculations.
I thought this would be really simple to do? I feel like this has to be a common problem for graphics code that deals with textures in different formats, or colorspaces, or whatever? Am I missing something obvious?
How do you do this without writing a bunch of versions of all of your shaders?
Here are functions for transforming RGBA to YUVA and vice versa on the fly.
float4 rgba2yuva(float4 rgba)
{
float4 yuva = float4(0.0);
yuva.x = rgba.r * 0.299 + rgba.g * 0.587 + rgba.b * 0.114;
yuva.y = rgba.r * -0.169 + rgba.g * -0.331 + rgba.b * 0.5 + 0.5;
yuva.z = rgba.r * 0.5 + rgba.g * -0.419 + rgba.b * -0.081 + 0.5;
yuva.w = rgba.a;
return yuva;
}
float4 yuva2rgba(float4 yuva)
{
float4 rgba = float4(0.0);
rgba.r = yuva.x * 1.0 + yuva.y * 0.0 + yuva.z * 1.4;
rgba.g = yuva.x * 1.0 + yuva.y * -0.343 + yuva.z * -0.711;
rgba.b = yuva.x * 1.0 + yuva.y * 1.765 + yuva.z * 0.0;
rgba.a = yuva.a;
return rgba;
}
I adapted the code from here: https://github.com/libretro/glsl-shaders/blob/master/nnedi3/shaders/
Simple OpenGL shaders are quite straightforward to port to Metal. I pretty much just changed the datatype vec4 to float4. If you want a half version, just substitute float4 for half4.
metal shader function ARK, now you can use #Jeshua Lacock to convert between the two.
// tweak your color offsets as desired
#include <metal_stdlib>
using namespace metal;
kernel void YUVColorConversion(texture2d<uint, access::read> yTexture [[texture(0)]],
texture2d<uint, access::read> uTexture [[texture(1)]],
texture2d<uint, access::read> vTexture [[texture(2)]],
texture2d<float, access::write> outTexture [[texture(3)]],
uint2 gid [[thread_position_in_grid]])
{
float3 colorOffset = float3(0, -0.5, -0.5);
float3x3 colorMatrix = float3x3(
float3(1, 1, 1),
float3(0, -0.344, 1.770),
float3(1.403, -0.714, 0)
);
uint2 uvCoords = uint2(gid.x / 2, gid.y / 2);
float y = yTexture.read(gid).r / 255.0;
float u = uTexture.read(uvCoords).r / 255.0;
float v = vTexture.read(uvCoords).r / 255.0;
float3 yuv = float3(y, u, v);
float3 rgb = colorMatrix * (yuv + colorOffset);
outTexture.write(float4(float3(rgb), 1.0), gid);
}
Good ref here , and then you can build pipelines or variants for processing specifically what you need like here
#include <metal_stdlib>
#include <simd/simd.h>
#include <metal_texture>
#include <metal_matrix>
#include <metal_geometric>
#include <metal_math>
#include <metal_graphics>
#include "AAPLShaderTypes.h"
using namespace metal;
// Variables in constant address space.
constant float3 lightPosition = float3(0.0, 1.0, -1.0);
// Per-vertex input structure
struct VertexInput {
float3 position [[attribute(AAPLVertexAttributePosition)]];
float3 normal [[attribute(AAPLVertexAttributeNormal)]];
half2 texcoord [[attribute(AAPLVertexAttributeTexcoord)]];
};
// Per-vertex output and per-fragment input
typedef struct {
float4 position [[position]];
half2 texcoord;
half4 color;
} ShaderInOut;
// Vertex shader function
vertex ShaderInOut vertexLight(VertexInput in [[stage_in]],
constant AAPLFrameUniforms& frameUniforms [[ buffer(AAPLFrameUniformBuffer) ]],
constant AAPLMaterialUniforms& materialUniforms [[ buffer(AAPLMaterialUniformBuffer) ]]) {
ShaderInOut out;
// Vertex projection and translation
float4 in_position = float4(in.position, 1.0);
out.position = frameUniforms.projectionView * in_position;
// Per vertex lighting calculations
float4 eye_normal = normalize(frameUniforms.normal * float4(in.normal, 0.0));
float n_dot_l = dot(eye_normal.rgb, normalize(lightPosition));
n_dot_l = fmax(0.0, n_dot_l);
out.color = half4(materialUniforms.emissiveColor + n_dot_l);
// Pass through texture coordinate
out.texcoord = in.texcoord;
return out;
}
// Fragment shader function
fragment half4 fragmentLight(ShaderInOut in [[stage_in]],
texture2d<half> diffuseTexture [[ texture(AAPLDiffuseTextureIndex) ]]) {
constexpr sampler defaultSampler;
// Blend texture color with input color and output to framebuffer
half4 color = diffuseTexture.sample(defaultSampler, float2(in.texcoord)) * in.color;
return color;
}
why use sPos.z here to get tescoord?
Out.shadowCrd.x = 0.5 * (sPos.z + sPos.x);
Out.shadowCrd.y = 0.5 * (sPos.z - sPos.y);
Out.shadowCrd.z = 0;
Out.shadowCrd.w = sPos.z;
It is a shader which achieves shadow mapping in "Shaders for Game Programming and Artists".
The first pass render depth texture in light space.( light is camera and watch towards the origin )
The second pass get the depth and calculate the shadow.
Before these codes, the model has already been transformed to light space.
Then the texcoord should be calculated to read depth texture.
But I can't understand the algorithm of calculating the texcoord. Why sPos.z will be here?
Here is the whole vertex shader of the second pass
float distanceScale;
float4 lightPos;
float4 view_position;
float4x4 view_proj_matrix;
float4x4 proj_matrix;
float time_0_X;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float3 normal: TEXCOORD0;
float3 lightVec : TEXCOORD1;
float3 viewVec: TEXCOORD2;
float4 shadowCrd: TEXCOORD3;
};
VS_OUTPUT vs_main(float4 inPos: POSITION, float3 inNormal: NORMAL)
{
VS_OUTPUT Out;
// Animate the light position.
float3 lightPos;
lightPos.x = cos(1.321 * time_0_X);
lightPos.z = sin(0.923 * time_0_X);
lightPos.xz = 100 * normalize(lightPos.xz);
lightPos.y = 100;
// Project the object's position
Out.Pos = mul(view_proj_matrix, inPos);
// World-space lighting
Out.normal = inNormal;
Out.lightVec = distanceScale * (lightPos - inPos.xyz);
Out.viewVec = view_position - inPos.xyz;
// Create view vectors for the light, looking at (0,0,0)
float3 dirZ = -normalize(lightPos);
float3 up = float3(0,0,1);
float3 dirX = cross(up, dirZ);
float3 dirY = cross(dirZ, dirX);
// Transform into light's view space.
float4 pos;
inPos.xyz -= lightPos;
pos.x = dot(dirX, inPos);
pos.y = dot(dirY, inPos);
pos.z = dot(dirZ, inPos);
pos.w = 1;
// Project it into light space to determine she shadow
// map position
float4 sPos = mul(proj_matrix, pos);
// Use projective texturing to map the position of each fragment
// to its corresponding texel in the shadow map.
sPos.z += 10;
Out.shadowCrd.x = 0.5 * (sPos.z + sPos.x);
Out.shadowCrd.y = 0.5 * (sPos.z - sPos.y);
Out.shadowCrd.z = 0;
Out.shadowCrd.w = sPos.z;
return Out;
}
Pixel Shader:
float shadowBias;
float backProjectionCut;
float Ka;
float Kd;
float Ks;
float4 modelColor;
sampler ShadowMap;
sampler SpotLight;
float4 ps_main(
float3 inNormal: TEXCOORD0,
float3 lightVec: TEXCOORD1,
float3 viewVec: TEXCOORD2,
float4 shadowCrd: TEXCOORD3) : COLOR
{
// Normalize the normal
inNormal = normalize(inNormal);
// Radial distance and normalize light vector
float depth = length(lightVec);
lightVec /= depth;
// Standard lighting
float diffuse = saturate(dot(lightVec, inNormal));
float specular = pow(saturate(
dot(reflect(-normalize(viewVec), inNormal), lightVec)),
16);
// The depth of the fragment closest to the light
float shadowMap = tex2Dproj(ShadowMap, shadowCrd);
// A spot image of the spotlight
float spotLight = tex2Dproj(SpotLight, shadowCrd);
// If the depth is larger than the stored depth, this fragment
// is not the closest to the light, that is we are in shadow.
// Otherwise, we're lit. Add a bias to avoid precision issues.
float shadow = (depth < shadowMap + shadowBias);
// Cut back-projection, that is, make sure we don't lit
// anything behind the light.
shadow *= (shadowCrd.w > backProjectionCut);
// Modulate with spotlight image
shadow *= spotLight;
// Shadow any light contribution except ambient
return Ka * modelColor +
(Kd * diffuse * modelColor + Ks * specular) * shadow;
}
I'm trying to port my engine to DirectX and I'm currently having issues with depth reconstruction. It works perfectly in OpenGL (even though I use a bit of an expensive method). Every part besides the depth reconstruction works so far. I use GLM because it's a good math library that has no need to install any dependencies or anything for the user.
So basically I get my GLM matrices:
struct DefferedUBO {
glm::mat4 view;
glm::mat4 invProj;
glm::vec4 eyePos;
glm::vec4 resolution;
};
DefferedUBO deffUBOBuffer;
// ...
glm::mat4 projection = glm::perspective(engine.settings.fov, aspectRatio, 0.1f, 100.0f);
// Get My Camera
CTransform *transform = &engine.transformSystem.components[engine.entities[entityID].components[COMPONENT_TRANSFORM]];
// Get the View Matrix
glm::mat4 view = glm::lookAt(
transform->GetPosition(),
transform->GetPosition() + transform->GetForward(),
transform->GetUp()
);
deffUBOBuffer.invProj = glm::inverse(projection);
deffUBOBuffer.view = glm::inverse(view);
if (engine.settings.graphicsLanguage == GRAPHICS_DIRECTX) {
deffUBOBuffer.invProj = glm::transpose(deffUBOBuffer.invProj);
deffUBOBuffer.view = glm::transpose(deffUBOBuffer.view);
}
// Abstracted so I can use OGL, DX, VK, or even Metal when I get around to it.
deffUBO->UpdateUniformBuffer(&deffUBOBuffer);
deffUBO->Bind());
Then in HLSL, I simply use the following:
cbuffer MatrixInfoType {
matrix invView;
matrix invProj;
float4 eyePos;
float4 resolution;
};
float4 ViewPosFromDepth(float depth, float2 TexCoord) {
float z = depth; // * 2.0 - 1.0;
float4 clipSpacePosition = float4(TexCoord * 2.0 - 1.0, z, 1.0);
float4 viewSpacePosition = mul(invProj, clipSpacePosition);
viewSpacePosition /= viewSpacePosition.w;
return viewSpacePosition;
}
float3 WorldPosFromViewPos(float4 view) {
float4 worldSpacePosition = mul(invView, view);
return worldSpacePosition.xyz;
}
float3 WorldPosFromDepth(float depth, float2 TexCoord) {
return WorldPosFromViewPos(ViewPosFromDepth(depth, TexCoord));
}
// ...
// Sample the hardware depth buffer.
float depth = shaderTexture[3].Sample(SampleType[0], input.texCoord).r;
float3 position = WorldPosFromDepth(depth, input.texCoord).rgb;
Here's the result:
This just looks like random colors multiplied with the depth.
Ironically when I remove transposing, I get something closer to the truth, but not quite:
You're looking at Crytek Sponza. As you can see, the green area moves and rotates with the bottom of the camera. I have no idea at all why.
The correct version, along with Albedo, Specular, and Normals.
I fixed my problem at gamedev.net. There was a matrix majorness issue as well as a depth handling issue.
https://www.gamedev.net/forums/topic/692095-d3d-glm-depth-reconstruction-issues
I am trying to build an infinite fog shader. This fog is applied on a 3D plane.
For the moment I have a Z-Depth Fog. And I encounter some issues.
As you can see in the screenshot, there are two views.
The green color is my 3D plane. The problem is in the red line. It seems that the this line depends of my camera which is not good because when I rotate my camera the line is affected by my camera position and rotation.
I don't know where does it comes from and how to have my fog limit not based on the camera position.
Shader
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform float4 _FogColor;
uniform sampler2D _CameraDepthTexture;
float _Depth;
float _DepthScale;
struct v2f {
float4 pos : SV_POSITION;
float4 projection : TEXCOORD0;
float4 screenPosition : TEXCOORD1;
};
v2f vert(appdata_base v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
// o.projection = ComputeGrabScreenPos(o.pos);
float4 position = o.pos;
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
float4 p = position * 0.5f;
p.xy = float2(p.x, p.y * scale) + p.w;
p.zw = position.zw;
o.projection = p;
// o.screenPosition = ComputeScreenPos(o.pos);
position = o.pos;
float4 q = position * 0.5f;
#if defined(UNITY_HALF_TEXEL_OFFSET)
q.xy = float2(q.x, q.y * _ProjectionParams.x) + q.w * _ScreenParams.zw;
#else
q.xy = float2(q.x, q.y * _ProjectionParams.x) + q.w;
#endif
#if defined(SHADER_API_FLASH)
q.xy *= unity_NPOTScale.xy;
#endif
q.zw = position.zw;
q.zw = 1.0f;
o.screenPosition = q;
return o;
}
sampler2D _GrabTexture;
float4 frag(v2f IN) : COLOR {
float3 uv = UNITY_PROJ_COORD(IN.projection);
float depth = UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, uv));
depth = LinearEyeDepth(depth);
return saturate((depth - IN.screenPosition.w + _Depth) * _DepthScale);
}
ENDCG
}
Next I want to rotate my Fog to have an Y-Depth Fog but I don't know how to achieve this effect.
I see two ways to acheive what you want:
is to render depth of your plane to texture and calculate fog based on difference of depth of plane and depth of object, 0 if obj depth is less and (objDepth - planeDepth) * scale if it is bigger)
Is to instead of rendering to texture calculate distance to plane in shader and use it directly.
I am not sure what you do since I am not very familiar with Unity surface shaders, but djudging from the code and result something different.
It seems that this is caused by _CameraDepthTexture, that's why depth is calculated with the camera position.
But I don't know how to correct it... It seems that there is no way to get the depth from another point. Any idea ?
Here is another example. In green You can "see" the object and the blue line is for me the fog as it should be.
First of all I'm new to XNA and HLSL so me knowledge is very limited.
I'm writing a small Application to display a digital elevation model consisting of 16Bit values in 2D by using different colors for different height.
The colormapping is done by a Pixelshader via a lookup texture.
At the moment I'm putting the values into red an green components of a texture2D and map them to colors in a 256x256 texture.
As the coloring is discrete/not continously I set minfilter/magfilter to point what leads to a blocky look when zooming in.
Is there a way to get the linear filtering back after the lookup? Or does anybody know a better way to do the mapping?
Shader:
sampler2D tex1 : register(s0) = sampler_state
{
MinFilter = Point;
MagFilter = Point;
MipFilter = linear;
};
texture2D lookupTex;
sampler2D lookup = sampler_state
{
Texture = <lookupTex>;
MinFilter = Point;
MagFilter = Point;
MipFilter = Point;
};
float4 PixelShaderLookup(float4 incol : COLOR, float2 UV : TEXCOORD0) : COLOR0
{
float4 inCol = tex2D(tex1, UV);
half3 scale = (256 - 1.0) / 256;
half3 offset = 1.0 / (2.0 * 256);
float4 outCol = tex2D(lookup, scale * inCol.gr + offset);
return outCol;
}
Thanks for your help and a happy new year :)