2 registered members (OptimusPrime, AndrewAMD),
14,580
guests, and 5
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Object Shader render to texture/bmap ... again.
#386689
11/08/11 14:10
11/08/11 14:10
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Hiya guys. I got a bee in my bonnet about texture-generation via shader again... Basically what Im trying to do is use a multi-texture shader to actually GENERATE a texture for later use. Im currently using the below PROTOTYPE shader to to apply and blend multiple textures onto an object based on its mesh's vertex-heights. This works fine as it is. (Prototype remember!) But what I actually WANT it to do is to just run the shader for one frame, take that 'generated' texture and 'save' it into another BMAP that I can then apply to the entity, so I dont need to generate the blended map every frame... Ive been playing with 'bmap_rendertarget' and 'view.PROCESS_TARGET' and the like, but I havent been able to get ANY data into the 'target' bmap at all... So I wont go over any of those tests, because I was probably using them completely wrong... I know this shader is horrible, and (ATM) ill-suited to the task, but its a prototype that was basically written to test proof-of-concept of the vertex-shader height extractions and the pixel-shader blending-based-on-height calculations. So I'm needing help PRIMARILY on the lite-c code 'around' the shader to capture the render-target. But help on any rotation/translation of the model object-space data will be appreciated...
//Application fed data
const float4x4 matWorldViewProj;
texture Sand_BM_bmap, Grass_BM_bmap, Rock_BM_bmap, Snow_BM_bmap;
// ColorMap Samplers
sampler SandSampler = sampler_state { Texture = <Sand_BM_bmap>; };
sampler GrassSampler = sampler_state { Texture = <Grass_BM_bmap>; };
sampler RockSampler = sampler_state { Texture = <Rock_BM_bmap>; };
sampler SnowSampler = sampler_state { Texture = <Snow_BM_bmap>; };
#define cMult 0.0001002707309736288
#define aSubtract 0.2727272727272727
float random(float4 t)
{
float a, b, c, d;
a=t.x+t.z*cMult+aSubtract-floor(t.x);
a*=a; b=t.y+a; b-=floor(b);
c=t.z+b; c-=floor(c); d=c;
a+=c*cMult+aSubtract-floor(a);
a*=a; b+=a; b-=floor(b);
c+=b; c-=floor(c);
return ((a+b+c+d)/4);
}
// Vertex Shader:
void TerrPaintVS( in float4 InPos: POSITION, in float2 InTex: TEXCOORD0,
out float4 OutPos: POSITION, out float2 OutTex: TEXCOORD0,
out float Height: TEXCOORD1 )
{
// Transform the vertex from object space to projected world space:
OutPos = mul(InPos, matWorldViewProj);
// Pass the texture coordinate to the pixel shader:
OutTex = InTex;
// Capture the Height of this vertex from object space... SEEMINGLY
Height = InPos.y;
// OPTIONALLY add some randomness to the demarkation line
Height += (random(InPos)*20)-5;
}
// Pixel Shader:
float4 TerrPaintPS( in float4 InPos: POSITION, in float2 InTex: TEXCOORD0,
in float Height:TEXCOORD1 ): COLOR
{
float4 Color = tex2D(SandSampler, InTex);
if(Height < 42) Color = lerp(tex2D(SandSampler,InTex), tex2D(GrassSampler,InTex), (Height-32)/10);
else if(Height < 75) Color = tex2D(GrassSampler, InTex);
else if(Height < 85) Color = lerp(tex2D(GrassSampler,InTex), tex2D(RockSampler,InTex), (Height-75)/10);
else if(Height < 120) Color = tex2D(RockSampler, InTex);
else if(Height < 130) Color = lerp(tex2D(RockSampler,InTex), tex2D(SnowSampler,InTex), (Height-120)/10);
else Color = tex2D(SnowSampler, InTex);
return Color;
}
// Technique:
technique AmbientTechnique
{
pass P0
{
VertexShader = compile vs_2_0 TerrPaintVS();
PixelShader = compile ps_2_0 TerrPaintPS();
}
}
/*
1 1 1 1 1 1 0.75 0.5 0.25 0
11 12 13 14 15 16 17 18 19 20
#define RANDOM_IA 16807
#define RANDOM_IM 2147483647
#define RANDOM_AM (1.0f/float(RANDOM_IM))
#define RANDOM_IQ 127773
#define RANDOM_IR 2836
#define RANDOM_MASK 123459876
int random_x;
float random ()
{
int k; float ans;
random_x ^= RANDOM_MASK;
k = random_x / RANDOM_IQ;
random_x = RANDOM_IA * (random_x - k * RANDOM_IQ ) - RANDOM_IR * k;
if ( random_x < 0 ) random_x += RANDOM_IM;
ans = RANDOM_AM * random_x;
random_x ^= RANDOM_MASK;
return ans;
}
float random ( float low, float high )
{
float v = random();
return low * ( 1.0f - v ) + high * v;
}
float2 random ( float2 low, float2 high )
{
float2 v = float2( random(), random() );
return low * ( 1.0f - v ) + high * v;
}
float3 random ( float3 low, float3 high )
{
float3 v = float3( random(), random(), random() );
return low * ( 1.0f - v ) + high * v;
}
void seed ( int value )
{
random_x = value;
random();
}
*/
Thanks guys... again.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Object Shader render to texture/bmap ... again.
[Re: EvilSOB]
#386694
11/08/11 14:39
11/08/11 14:39
|
Joined: Mar 2006
Posts: 3,538 WA, Australia
JibbSmart
Expert
|
Expert
Joined: Mar 2006
Posts: 3,538
WA, Australia
|
I would, in the vertex shader, use the vertex's u,v coordinates converted to screen-space for rendered position, so that this trick could be used for any model (not just a terrain). I guess I'd have a function that, given an entity, will create a view that targets its skin, assign your clever shader to the view, and use a material event to make sure only the entity concerned gets rendered (perhaps using and analysing that view's genius?). wait(1). Then remove the view. That's the theory, anyway. I'd love to give it a go, but I'm otherwise occupied 
Formerly known as JulzMighty. I made KarBOOM!
|
|
|
Re: Object Shader render to texture/bmap ... again.
[Re: JibbSmart]
#386699
11/08/11 15:15
11/08/11 15:15
|
Joined: Apr 2007
Posts: 3,751 Canada
WretchedSid
Expert
|
Expert
Joined: Apr 2007
Posts: 3,751
Canada
|
HeelX posted a code snippet that does exactly what you want (render a terrain into a texture) via RTT. I'm sure that you can still find it via an forum search.
Shitlord by trade and passion. Graphics programmer at Laminar Research. I write blog posts at feresignum.com
|
|
|
Re: Object Shader render to texture/bmap ... again.
[Re: JibbSmart]
#386701
11/08/11 15:23
11/08/11 15:23
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Tried it with multiple permutations, and failed. Based on the example in the manual under "bmap_rendertarget". I could never got any 'new' data into the target bmap, it stayed unchanged.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Object Shader render to texture/bmap ... again.
[Re: EvilSOB]
#386703
11/08/11 15:29
11/08/11 15:29
|
Joined: Mar 2006
Posts: 3,538 WA, Australia
JibbSmart
Expert
|
Expert
Joined: Mar 2006
Posts: 3,538
WA, Australia
|
bmap_rendertarget is specifically for using multiple render targets in one shader. It's also somewhat redundant (it works, but VIEWs render targets can now be manipulated/changed through their target1...target3 BMAP pointers). These will only work if your pixel shader has "out float4 colour1: COLOR1" and the like to render to additional render targets.
Try using view.bmap, instead. This is the easiest means of render-to-texture, as the view's output will go straight to that bmap. In the meantime, I can't resist: I'm going to try a quick test.
Formerly known as JulzMighty. I made KarBOOM!
|
|
|
Re: Object Shader render to texture/bmap ... again.
[Re: JibbSmart]
#386704
11/08/11 15:45
11/08/11 15:45
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
JibbSmart: Useful info. With your test ... please do!! All I really need is functional code (both lite-c and FX) to get an object shader into a bmap...
JustSid: Finally found it, and a great example of bmap_process! Certainly goes into my archives. BUT, it is 'just' a post-processing shader in this instance, and I cant currently get to the height-data EXCEPT by creating a bmap and 'pixel-to-bmap'ing one together and that will lose me all the speed Im trying to gain by this shader...
Hopefully Jibb may come up with something. Im about to try playing with the target1..target3 pointers to see how I go...
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Object Shader render to texture/bmap ... again.
[Re: EvilSOB]
#386713
11/08/11 16:48
11/08/11 16:48
|
Joined: Mar 2006
Posts: 3,538 WA, Australia
JibbSmart
Expert
|
Expert
Joined: Mar 2006
Posts: 3,538
WA, Australia
|
Alright! Here's a 90-line example:
#include <acknex.h>
#include <default.c>
BMAP *targetBmap = "#256x256x32";
ENTITY *blob, *earth, *writeTarget;
function skinChangeEvent() {
if (me == render_view.genius)
return 0;
else
return 1;
}
MATERIAL *skinChangeMat = {
effect = "
texture entSkin1;
sampler SkinSampler = sampler_state { Texture = <entSkin1>; };
float4x4 matWorld;
float4x4 matWorldViewProj;
float4 vecSunDir;
void VS(in float3 inNormal: NORMAL,
in float2 inTex: TEXCOORD0,
out float4 outPos: POSITION,
out float2 outTex: TEXCOORD0,
out float3 outNormal: TEXCOORD1) {
outPos = float4(inTex.x * 2.0 - 1.0, -inTex.y * 2.0 + 1.0, 1.0, 1.0);
outTex = inTex;
outNormal = mul(inNormal, (float3x3)matWorld);
}
float4 PS(in float2 inTex: TEXCOORD0,
in float3 inNormal: TEXCOORD1): COLOR0 {
float4 colour = tex2D(SkinSampler, inTex);
colour.rgb *= saturate(dot(-vecSunDir, normalize(inNormal)));
return colour;
}
technique t {
pass p {
CullMode = None;
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}
";
flags = ENABLE_RENDER;
event = skinChangeEvent;
}
function updateView() {
beep();
VIEW *v = view_create(1);
v.bmap = targetBmap;
v.size_x = v.size_y = 256;
vec_set(v.x, camera.x);
vec_set(v.pan, camera.pan);
v.flags |= SHOW;
v.genius = writeTarget;
v.material = skinChangeMat;
wait(1);
ptr_remove(v);
}
function switchTarget() {
beep();
if (writeTarget == blob)
writeTarget = earth;
else
writeTarget = blob;
}
function main() {
level_load(NULL);
writeTarget = blob = ent_create("blob.MDL", vector(0, -20, 0), NULL);
earth = ent_create("earth.MDL", vector(0, 20, 0), NULL);
camera.x -= 100;
on_space = updateView;
on_enter = switchTarget;
while (1) {
DEBUG_BMAP(targetBmap, 0, 1);
wait(1);
}
}
Copy earth.mdl and blob.mdl from your samples folder to whatever folder you test this code in, and then it should be good to go. Hit [SPACE] to render the target's skin to a bmap that'll be displayed on-screen at the top-left. Hit [ENTER] to toggle between targets (earth or the blob). To demonstrate the use of an actual shader, simple diffuse lighting is baked into the skin. These skins aren't applied to the models themselves, but could be. In fact, a relatively well-known yet hardly-used effect is to render shadows to a texture and post-process them from there (such as blurring the red channel for a sub-surface scattering effect, which was first utilised in the Matrix sequels (and I mean the movies, not games!) for realistically rendering skin, if I recall correctly). This is probably hardly ever used because each instance of the entity would require its own skin, making it memory-intensive. Let me know if anything doesn't appear to make sense straight away. I'm getting back to work, but I'll check in every now and then (like I usually do). It's worth noting that if the objects aren't in view of the temporarily created view, they'll get culled automatically (out of my hands, AFAIK), so in application you'll want to place the view such that the entity in question will certainly not get culled. EDIT: The weird artifacts on blob's baked skin are because blob's u/v coordinates overlap themselves. EDIT2: Changed the shader a little so the y axis isn't mirrored.
Last edited by JibbSmart; 11/08/11 17:09.
Formerly known as JulzMighty. I made KarBOOM!
|
|
|
Re: Object Shader render to texture/bmap ... again.
[Re: JibbSmart]
#386715
11/08/11 17:11
11/08/11 17:11
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Excellent work Jibb.. HUGE thankk you.
BUT, I aint looking at it YET. My one is almost running, and I dont want to lose my train of thought...
But I am hugely grateful anyway!
I'll post how I go with mine, THEN I'll look at yours, filtch anything in it I feel I could use...
I shall return!
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Object Shader render to texture/bmap ... again.
[Re: JibbSmart]
#386728
11/08/11 19:10
11/08/11 19:10
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Hmmm.. bogged down. I think my shader-part is completely worthless.
Im getting the heights down to the pixel-shader, but the x-y coords are useless.
Im going to take a look at JibbSmarts when Ive had a sleep. The fact it is using 'spherical' objects is making it tricky to visually figure out.
I need some ZZZZ's first...
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
|