FTexture2DRHIRef texture and vertex shader
Closed this issue · 10 comments
Hello, I need a little help about two points.
I'm testing the plugin and I want to create a FTexture2DRHIRef texture to give as input directly to the pixel shader, How Can I do it? I did:
FRHIResourceCreateInfo CreateInfo;
InputTexture = RHICreateTexture2D(960, 540, PF_R32_UINT, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo);
but then how can I fill the data? for example how to obtain a black texture?
Second question is, in the PixelShaderExample I found out the MainVertexShader function.
How can I use it? because if for example I set
OutPosition = InPosition*3;
nothing change! instead I was expecting to see cubes in the example enlarge three time themselves. So how I can use properly the vertex shader?
I’m sorry for the newby question,
I’m very grateful for your help,
Thank you for the (unexpected) quick reply!
OK, regarding the FRHI command I found this:
https://docs.unrealengine.com/latest/INT/API/Runtime/RHI/FRHICommandList/index.html
I will look to the functions listed here.
Can you suggest a more verbose documentation or simple related tutorial?
Regarding DirectX/OpenGL. I know a little of OpenGL. In fact, I wrote some (working) shaders in OpenGL but now I have the task to implement the same here in UE4 (and so googling and searching I found your plugin!). UE4 is so big that I'm confused!
So, I will try the functions as soon as possible and I will let you know (and I will write a reply here hoping to be help for someone in future). Unfortunately I can't access the working station now so I think I will try in the next days.
For what regards the second question, the render target one, I will read something about that. Just to be sure we have the same vocabulary, with "render target" are we speaking about "buffers" like in OpenGL?
Again thank you, I will write results and/or new doubts when I will read something more about the topic or tried solutions. Sorry for my bad English I'm not a native speaker.
Hello again, Sorry if I bore you, If I do this please tell me and I will write these question on the ue4 general forum.
So I tried to use the ClearColorTexture() function but in order to use it I need a RHICmdList, Which I create in the line above.
//MY STUFF
FRHIResourceCreateInfo CreateInfo;
FLinearColor my_color = FLinearColor(1, 1, 0, 1);
InputTexture = RHICreateTexture2D(960, 540, PF_R32_UINT, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo);
/* Get global RHI command list */
FRHICommandListImmediate& myRHICmdList = GRHICommandList.GetImmediateCommandList();
myRHICmdList.ClearColorTexture(InputTexture, my_color, FIntRect());
//end my stuff
If I try to do something like this (this code is placed between the execution of the compute shader and the pixel shader).. ue4 crashes.
If I try to access single pixel like in this example_https://answers.unrealengine.com/questions/25594/accessing-pixel-values-of-texture2d.html
//my stuff due
FColor my_FColor = FColor(1, 0, 0, 1);
FTexture2DMipMap* MyMipMap = &InputTexture->GetTexture2D()->PlatformData->Mips[0];
FByteBulkData* RawImageData = &MyMipMap->BulkData;
FColor* FormatedImageData = static_cast<FColor*>(RawImageData->Lock(LOCK_READ_ONLY));
uint32 TextureWidth = MyMipMap->SizeX, TextureHeight = MyMipMap->SizeY;
FColor PixelColor;
for (int i = 0; i < TextureWidth*TextureHeight; i++) {
FormatedImageData[i] = my_FColor;
}
/*
uint8 PixelX = 5, PixelY = 10;
if (PixelX >= 0 && PixelX < TextureWidth && PixelY >= 0 && PixelY < TextureHeight)
{
PixelColor = FormatedImageData[PixelY * TextureWidth + PixelX];
}*/
RawImageData->Unlock();
InputTexture->GetTexture2D()->PlatformData->Mips[0].BulkData.Unlock();
//end my stuff due
The compiler tells me that FRHITexture2D does not contain any member callded “Platform Data”.
Now I will study the target buffer to solve the vertex shader issue. thanks you.
maybe should I execute that code in Render thread?
I see also from your example that I should use
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER macro.
but I dont understand the params I should pass to this macro for apply these operation.
Ok, maybe I'm near,
I use this code
//MY STUFF
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(void, FTexture2DRHIRef, InputTexture, InputTexture ,
{
FRHIResourceCreateInfo CreateInfo;
InputTexture = RHICreateTexture2D(960, 540, PF_R32_UINT, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo);
// Write the contents of the texture.
uint32 DestStride;
uint32* DestBuffer = (uint32*)RHILockTexture2D(InputTexture, 0, RLM_WriteOnly, DestStride, false);
int BufferSize = 960 * 540 * 4;
uint8 * SourceBuffer = new uint8[BufferSize];
for (int i = 0; i < BufferSize; i++) {
SourceBuffer[i] = 20;
}
FMemory::Memcpy(DestBuffer, SourceBuffer, BufferSize);
RHIUnlockTexture2D(InputTexture, 0, false);
}
);
I'm not sure about the macro parameter.
after this code I exectute
PixelShading->ExecutePixelShader(RenderTarget, InputTexture,
FColor(EndColorBuildup * 255, 0, 0, 255), ComputeShaderBlend);
My Pixel shader is
void MainPixelShader(
in float2 uv : TEXCOORD0,
out float4 OutColor : SV_Target0
)
{
//First we need to unpack the uint material and retrieve the underlying R8G8B8A8_UINT values.
float sizeX, sizeY;
TextureParameter.GetDimensions(sizeX, sizeY);
uint packedValue = TextureParameter.Load(int3(sizeX * uv.x, sizeY * uv.y, 0));
uint r = (packedValue & 0x000000FF);
uint g = (packedValue & 0x0000FF00) >> 8;
uint b = (packedValue & 0x00FF0000) >> 16;
uint a = (packedValue & 0xFF000000) >> 24;
OutColor = float4(r,g,b,a) ;
}
So I'm sampling from the texture I wrote right?
unfortunatly is not working because I can see only black cubes whatever values I put inside texture elements...
Well,
Onestly I'm quite disoriented,
I'm creating the texture like I wrote above. So I have this 960*540 resolution texture where each textel is 4 bytes.
I tried to sample in this way in the hlsl shader
OutColor = TextureParameter.Sample(mySampler, float2(sizeX * uv.x, sizeY * uv.y));
having the foresight to change the input from
Texture2D <uint> TextureParameter;
to
Texture2D TextureParameter;
unfortunatly I still see black cubes.
I've asket another method to write into the texture, I received help in the forum, here is my code now, as you can see after I modify the texture I call the pixel shader.
//MY STUFF
//Create Texture
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(FCreateActorsTexure,
FTexture2DRHIRef, TexurePtr, InputTexture,
{
FRHIResourceCreateInfo CreateInfo;
TexurePtr = RHICreateTexture2D(960, 540, PF_R32_UINT, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo);
//FRHICommandListImmediate& RHICmdList = GRHICommandList.GetImmediateCommandList();
//RHICmdList.ClearColorTexture(TexurePtr, FLinearColor::Red, FIntRect());
}
);
//Update Texture
uint32 BufferSize = 960 * 540 * 4;
uint8 * SourceBuffer = new uint8[BufferSize];
for (uint32 i = 0; i < BufferSize; i++)
{
SourceBuffer[i] = 20;
}
ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER(FUpdateActorsTexure,
FTexture2DRHIRef, TexurePtr, InputTexture,
uint8*, NewData, SourceBuffer,
uint32, Size, BufferSize,
{
uint32 DestStride;
uint32* DestBuffer = (uint32*)RHILockTexture2D(TexurePtr, 0, RLM_WriteOnly, DestStride, false);
FMemory::Memcpy(DestBuffer, NewData, Size);
RHIUnlockTexture2D(TexurePtr, 0, false);
delete[] NewData;
}
);
PixelShading->ExecutePixelShader(RenderTarget, InputTexture, FColor(EndColorBuildup * 255, 0, 0, 255), ComputeShaderBlend);
Hello,
As promised I'll put something working hoping that can be usefull to someone. the code is not clean. This Is the original one in the Demo + some lines that load a custom texture to the pixel shader.
FTexture2DRHIRef InputTexture = NULL;
if (ComputeShading) {
ComputeShading->ExecuteComputeShader(TotalElapsedTime);
InputTexture =
ComputeShading->GetTexture(); //This is the output texture from the compute shader that we will pass to the pixel shader.
}
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(FCreateActorsTexure,
FTexture2DRHIRef, TexurePtr, InputTexture,
{
FRHIResourceCreateInfo CreateInfo;
TexurePtr = RHICreateTexture2D(960, 540, PF_R8G8B8A8, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo);
}
);
//Update Texture
uint32 BufferSize = 960 * 540 * 4;
uint8 * SourceBuffer = new uint8[BufferSize];
uint8 myrand = (FMath::RandRange(0, 255));
for (uint32 i = 0; i < BufferSize; i=i+4)
{
SourceBuffer[i] = 0;
SourceBuffer[i+1] = 255;
SourceBuffer[i+2] = 0;
SourceBuffer[i+3] = 255;
}
ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER(FUpdateActorsTexure,
FTexture2DRHIRef, TexurePtr, InputTexture,
uint8*, NewData, SourceBuffer,
uint32, Size, BufferSize,
{
uint32 DestStride;
uint8* DestBuffer = (uint8*)RHILockTexture2D(TexurePtr, 0, RLM_WriteOnly, DestStride, false);
FMemory::Memcpy(DestBuffer, NewData, Size);
RHIUnlockTexture2D(TexurePtr, 0, false);
delete[] NewData;
}
);
ComputeShaderBlend = FMath::Clamp(ComputeShaderBlend +
ComputeShaderBlendScalar * DeltaSeconds, 0.0f, 1.0f);
PixelShading->ExecutePixelShader(RenderTarget, InputTexture,
FColor(EndColorBuildup * 255, 0, 0, 255), ComputeShaderBlend);
}
for example above I create a green texture (0, 255, 0,255)
here the modified pixel shader
Texture2D <uint> TextureParameter;
SamplerState mySampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
void MainPixelShader(
in float2 uv : TEXCOORD0,
out float4 OutColor : SV_Target0
)
{
//First we need to unpack the uint material and retrieve the underlying R8G8B8A8_UINT values.
float sizeX, sizeY;
TextureParameter.GetDimensions(sizeX, sizeY);
uint packedValue = TextureParameter.Load(int3(uv.x,uv.y, 0));
uint r = (packedValue & 0x000000FF);
uint g = (packedValue & 0x0000FF00) >> 8;
uint b = (packedValue & 0x00FF0000) >> 16;
uint a = (packedValue & 0xFF000000) >> 24;
//sampling
// OutColor = TextureParameter.Sample(mySampler, float2(sizeX * uv.x, sizeY * uv.y));
OutColor = float4(r,g,b,a);
//OutColor = float4(255,255,0,255); //yellow
}
thanks for the help temaran.
I have a lot of doubts,
why if I execute
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(FCreateActorsTexure,
FTexture2DRHIRef, TexurePtr, InputTexture,
{
FRHIResourceCreateInfo CreateInfo;
TexurePtr = RHICreateTexture2D(960, 540, PF_R8G8B8A8, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo);
}
);
whitout before executing this:
if (ComputeShading) {
ComputeShading->ExecuteComputeShader(TotalElapsedTime);
InputTexture =
ComputeShading->GetTexture(); //This is the output texture from the compute shader that we will pass to the pixel shader.
}
It crashes?
Then, How to bind new parameters to the shaders?