-
RAYMARCHING HLSL/GLSL (DX/OpenGL)
Hello
I want to open this thread because I am very interested in this topic.
Probably, however, as often happens to me I will not find interested people, but I try anyway.
preamble.
Some time ago I came across a rendering technique called RayMarching. In my opinion it is the most interesting that exists. Because it allows you to achieve superb effects and quality without having to deal with Meshes.
It consists in having as input the screen pixel coordinates (UV) normalized in the range (-1 to 1, -1 to 1).
For each coordinate a Ray is started from the observation point to it (screen pixel).
Using this Ray we measure the distance from the objects we want to represent using the SDF technique.
Once the distance has been obtained, the normal of the encountered surface is calculated.
This normal (together with that of the direction of a light source) is used to calculate the diffusion and refraction of light.
In addition, the shadow can also be calculated.
All this if you intend to create a "realistic" rendering, but there is also the possibility of creating "abstract" outputs.
Here you can see an exhaustive and better explanation of the above.
https://www.youtube.com/watch?v=PGtv-dBi2wE
And here is something I created with pure VB6
https://www.youtube.com/watch?v=l-kWI3dlxas
https://www.youtube.com/watch?v=QVZIy8wXVSM
https://www.youtube.com/watch?v=OFuEnjrSQiM
OK, all great, but then what's the problem?
Well, it took a lot of processing time to get these animations. (many seconds per frames)
For each pixel the amount of calculations to be carried out is truly remarkable and performing this with VB6 is an infinite slowness.
But here it comes wqweto that pleased us with a Type Library for DirectX 11.
Exploring a bit of the examples provided in wqweto library we can find the HLSL Code.
https://en.wikipedia.org/wiki/Cg_(programming_language)
This DX-compiled and executed code is surely supersonic when compared to VB6.
I am sure it is possible to realize RayMarching using the HLSL code. (integrated via wqweto library with VB6)
And not taking advantage of this opportunity would be a mortal sin.
What we need is someone quite knowledgeable about VertexShader and FragmentShader (PixelShader)
That is all for the moment.
v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
EDIT 29/12/2020
Progress has been made.
In this starter post I will keep the main content list updated.
- DX11 Shader (No variables) by Me
- TrueVision3D Shader (Initial example) by Me
- DX9 Shader (WITH 1 Variable) by TheTrick
- DX9 Shader (WITH 1 Variable) by Me
- TrueVision3D Shader 2 (second example with FLOAT3) by Me
- DX9 Shader (more than 1 Variable) by TheTrick
The ones made by me are downloadable all at once here
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
EUREKA!!!! I SUCCEEDED!
Download the Code and Take a look
- Github Repo
- ZIP
As a starting point I used wqweto tutorial 03.
(this uses a texture but I don't use it, but I started from here because of the Quad)
As a reference I used the "RayMarching for Dummy" video and wrote the code in HLSL. (with small customizations)
The first version is in the "01. Test" folder
I discovered a very sad thing, it seems that the HLSL cannot access the Time or GetTime (iTime) function so in this demo the light is static.
Good start, then will come other questions and problems to solve ...
such as:
- How to pass variables (inside Do While m_isRunning LOOP) from VB6 to Shader ?
and some other ones a little bit off-topic (but surely interesting):
- How to pass an image (Texture) from VB6 memory to Shader ?
- How to retrieve the shader output pixels from it to VB6 ?
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Attachment 179674
-2147467259
I get this error, both in IDE and compiled.
so I can't get past this:
Code:
If hResult < 0 Then
Err.Raise hResult, "D3D11CreateDevice"
End If
the TLB is added of course.
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Quote:
Originally Posted by
baka
Attachment 179674
-2147467259
I get this error, both in IDE and compiled.
so I can't get past this:
Code:
If hResult < 0 Then
Err.Raise hResult, "D3D11CreateDevice"
End If
the TLB is added of course.
Hi
do you have same problems with "pure" DirectX 11 for VB6 1.0 Type Library ?
I suppose so.
I have no idea, try asking wqweto.
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
it seems to be #Const DebugBuild = True
need to be set to false or I can't run it!
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Quote:
Originally Posted by
baka
it seems to be #Const DebugBuild = True
need to be set to false or I can't run it!
That is weird because reexre sample is retrying D3D11CreateDevice w/o D3D11_CREATE_DEVICE_DEBUG flag if initialization failed.
The original problem is that you don't have DX11 SDK installed (which is normal) so can use the runtime only in release mode (no debug facilities shipped in OS provided one).
cheers,
</wqw>
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
I managed to add the variable time (essential.)
After countless attempts using the DX11 TypeLib I gave up.
I found an excellent solution: Using the free TV3D engine.
Just Download and install "TV3D 6.5 SDK Only"
http://www.truevision3d.com/downloads.php (few MBs)
With TV3D it's really much simpler!
Although I admit that I ran into quite a few difficulties that I solved with intensive research on the internet.
I am happy with the result. It is also very easy to pass Variables from VB6 to the shader (as in Godot).
The visible result (three objects in black and white) is not very interesting for the moment, but look at the FPS!
I just finished it right now and without much improvement I shared it, couldn't wait.
Download the Code and Take a look
GitHub Repo
ZIP
Files are in folder "03 TRUEVISION3D OK"
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Do you have complete shaders? I can help you to integrate them to D3D9 if you have shaders.
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Quote:
Originally Posted by
The trick
Do you have complete shaders? I can help you to integrate them to D3D9 if you have shaders.
Yes I have.
I wrote them in HLSL.
Here it is the code of the one I talked about in the previous post.
To see it you have to instal TV3D (that uses DX9), and download the code as explained above.
If you can help me to integrate them to D3D9 would be great!
So I could avoid using TV3D!
btw
A "must" thing have to be the possibility to "send" variables from VB6 to the shader.
EG with TV3D just use Shader.SetEffectParamFloat
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
This is done using my example above as a starting point.
It runs at around 25 FPS
ie it draws a frame in 1/25 of a second while using pure VB6 it took about 1.5 - 2 minutes per frame.
Original 480p
https://www.youtube.com/watch?v=QWkzzvo2cik
(the LOW FPS displayed is due to saving to disk each frame. )
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
I made the example of using your HLSL code in DirectX9. See example here.
https://www.vbforums.com/images/ieimages/2020/12/2.gif
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Quote:
Originally Posted by
The trick
I made the example of using your HLSL code in DirectX9. See example
here.
...
Fantastic ! Thanks!
Well, I'll study it!
I'll point out two things:
one is the oversight in the link. correct the last word of the link: Raymatching -> Raymarching
The other one is more important:
Please on gituhub change the .gitattributes (<- Here is what I use) file otherwise there are problems with the interpretation of the newline character, and it does not open the files correctly, for example when I open a .FRM file in VB6 it appears even this in the editor (of VB6 IDE)
Code:
VERSION 5 #
Begin VB.Form frmMain
BorderStyle = 1 'Fixed Single
Caption = "Raymarching using Direct3D9 shaders"
ClientHeight = 8085
ClientLeft = 45
ClientTop = 375
ClientWidth = 12705
LinkTopic = "Form1"
MaxButton = 0 'False
MinButton = 0 'False
ScaleHeight = 8085
ScaleWidth = 12705
StartUpPosition = 3 'Windows Default
Begin VB.Timer tmrFPS
Interval = 1000
Left = 4320
Top = 3540
End
End
I found this: https://gist.github.com/ennerperez/6...868c05abc94e9b
Code:
# Set the default behavior, in case people don't have core.autocrlf set.
* binary
*.bas text eol=crlf
*.frm text eol=crlf
*.ctl text eol=crlf
*.log text eol=crlf
*.vbp text eol=crlf
*.cls text eol=crlf
*.vbw text eol=crlf
*.dsr text eol=crlf
*.ini text eol=crlf
*.txt text eol=crlf
*.cfg text eol=crlf
*.md text eol=crlf
don't know which one is better ...
(should be enough to put it in the root folder.)
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Quote:
one is the oversight in the link. correct the last word of the link: Raymatching -> Raymarching
Oh yes, was my mistake. I've fixed.
Quote:
Please on gituhub change the .gitattributes (<- Here is what I use) file otherwise there are problems with the interpretation of the newline character, and it does not open the files correctly, for example when I open a .FRM file in VB6 it appears even this in the editor (of VB6 IDE)
Thanks, i've fixed that (always forgot about the .gitignore/.gitattributes files).
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Quote:
Originally Posted by
reexre
I found this:
https://gist.github.com/ennerperez/6...868c05abc94e9b
Code:
# Set the default behavior, in case people don't have core.autocrlf set.
* binary
*.bas text eol=crlf
*.frm text eol=crlf
*.ctl text eol=crlf
*.log text eol=crlf
*.vbp text eol=crlf
*.cls text eol=crlf
*.vbw text eol=crlf
*.dsr text eol=crlf
*.ini text eol=crlf
*.txt text eol=crlf
*.cfg text eol=crlf
*.md text eol=crlf
Must set diff option like this
* binary diff
. . . otherwise risk loosing the ability to inspect diffs in visual tools like SourceTree. (I forgot to set it on all 16000+ PSC repos so I know from first hand. :-))
This config is missing on quite a few native VB6 source files (like .pag, .dob, .vbr, etc.) but includes .md, .ini and more non-VB6 non-source files for no apparent reason. Keeping config files in binary is enough not to screw line-endings because in binary whatever the original file uses for line-endings is kept in the source control too. On the other hand marking non-VB6 source files as text has some merrit for inspecting diffs only.
For a full list of native VB6 source file + non-VB6 source files (like C/C++, PHP, whatever) as extracted by file extension from all 16000+ PSC repos you can check out this .gitattributes.
cheers,
</wqw>
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Quote:
for a full list of native vb6 source file + non-vb6 source files (like c/c++, php, whatever) as extracted by file extension from all 16000+ psc repos you can check out
this .gitattributes.
do not work to me!
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Thanks TheTrick I am very grateful to you.
I also really appreciate the ability to load pre-compiled Shaders, great!
I created a class to do only this.
https://github.com/miorsoft/VB6-HLSL...er/04%20%20DX9
Now I have to take other steps to complete this class:
- How do you add a "variable"?
- How do you add / manage multiple variables?
- How do the Array variables work (in this case)? (Array of float array of float3)
Then there are others (but in case we see later) such as:
- Send Bytes array of texture from VB6 to shader
- (Inside Shader duplicate in and manipulate)
- Get BytesArray of manipulated texture back to VB6
I hope you can Help!
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
I can help you but i need the working shader (a typical case of your task) because i don't fully understand what's exactly you try to do.
In order to get the calculated data you could use the render to texture. See the 3D Form example where you get the rendered quad back from GPU.
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Quote:
Originally Posted by
The trick
I can help you but i need the working shader (a typical case of your task) because i don't fully understand what's exactly you try to do.
Main Topic:
1) How to have/manage multiple Variables ( the using of cPSConstTbl)
and other types of variables such as Arrays and FLOAT3
I'll show here a/some working shader examples as soon as I can.
2) Secondary. The other questions I put are not related to RayMarching, but about a sort of image-manipulation done through the GPU. We can see them in a second time.
- Send Bytes array of texture from VB6 to shader
- Get BytesArray of manipulated texture back to VB6
-
Re: RAYMARCHING using wqweto DirectX 11 for VB6 Type Library
Here's a new example (with a rather dumb scene) [that uses Truevision3D]
https://github.com/miorsoft/VB6-HLSL...EVISION3D%20OK
The main difference from the other example is that it has more variables ... also of type FLOAT3
In TV3D it is very simple: there are the functions:
Shader.SetEffectParamFloat ()
Shader.SetEffectParamVector3 ()
And this: (that I have yet to understand how it works)
Shader.SetEffectParamVectorArray3 ()
I would like to be able to pass Vector3 arrays (even two-dimensional)
In the Shader code the variables (called Parameters / Registers) to be exchanged are described as follows:
uniform float TIME1 = 0.0; // Variabliles passed from / To VB6
uniform float3 CAMLOOKAT = float3 (10,0,10);
Then with TV3D you can Read (GetEffectParamVector3) or Write (SetEffectParamVector3)
PS: This has camera Vector up (0,1,0)
-
1 Attachment(s)
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
I changed my original example to use the new shader. I made the small changes in the shader because your shader tries to change the constant 'SunLight'. I've added a global variable. Because of the shader doesn't use the TIME1 constant the optimizer removes it (you can disable optimizer if you need).
The SetPixelShaderConstantF method accepts the 4-float-vectors argument so you just use SetPixelShaderConstantF reg, vec, 1 which means set a vector argument.
https://www.vbforums.com/images/ieimages/2021/01/1.png
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Quote:
Originally Posted by
The trick
...
The SetPixelShaderConstantF method accepts the 4-float-vectors argument so you just use SetPixelShaderConstantF reg, vec, 1 which means set a vector argument.
...
thanks!
I was able to pass arrays too.
But I was a little confused in regards to
the second term of SetPixelShaderConstantF which should be a float4, instead your example passes a D3DVECTOR which is float3 (tCamPos).
From what I understand it should be D3DVECTOR4.
For only one value this still works but when passing an array things go wrong and you need to use D3DVECTOR4.
When I pass an array and use D3DVECTOR4 I suppose that even in the HLSL shader side the type must be defined as float4, right? ( float4 myarray[] )
(when, in this context, I use float3 in the HLSL sometimes it goes sometimes not.)
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Quote:
Originally Posted by
reexre
thanks!
I was able to pass arrays too.
But I was a little confused in regards to
the second term of SetPixelShaderConstantF which should be a float4, instead your example passes a D3DVECTOR which is float3 (tCamPos).
From what I understand it should be D3DVECTOR4.
For only one value this still works but when passing an array things go wrong and you need to use D3DVECTOR4.
When I pass an array and use D3DVECTOR4 I suppose that even in the HLSL shader side the type must be defined as float4, right? ( float4 myarray[] )
(when, in this context, I use float3 in the HLSL sometimes it goes sometimes not.)
It's because optimization. The shaders use only the 3 components so we can send D3DVECTOR (the fourth component contains the garbage from the stack). When you pass an array you should pass D3DVECTOR4 (or matrix) of course.
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
here's how I'm having fun :)
https://www.youtube.com/watch?v=xVBy-xW0eeU
this is the HLSL shader code used:
Code:
// - Roberto Mior
// - reexre
#define MAXSTEPS 128 //125
#define MAX_DIST 6000.0 //5000.0
#define EPS 0.125 // 0.0625 //0.08
#define NCRE 3
//uniform float TIME1 = 0.0;
//uniform float TERRAIN[40][40];
uniform float3 CAMPOS = float3(1.0,1.0,1.0);
uniform float3 CAMLOOKAT = float3(0.0,0.0,0.0);
uniform float3 P1[NCRE];
uniform float3 P2[NCRE];
uniform float3 P3[NCRE];
uniform float3 P4[NCRE];
uniform float3 P5[NCRE];
uniform float3 P6[NCRE];
uniform float3 P7[NCRE];
uniform float3 P8[NCRE];
uniform float3 P9[NCRE];
uniform float3 P0[NCRE];
uniform float3 SunLight=float3(1.0,1.0,1.0);
static float C12671_D_4363920 = 2.9035821004968e-03 ;
static float C2363_D_18183 = 0.129956552824066 ;
static float C121_D_16662240 = 7.26192876828086e-06 ;
static float C601_D_872784 = 6.88601074263506e-04 ;
static float C445_D_12122 = 3.67101138426002e-02 ;
struct VS_Input {
float2 pos : POSITION;
float2 uv : TEXCOORD;
};
struct VS_Output {
float4 pos : POSITION;
float2 uv : TEXCOORD;
};
/////////////////////////////////////
//// RAYMARCHING
/////////////////////////////////////
///////////////////////////////////////// SDF FUNCTIONS
float sdSphere( float3 p, float s )
{
return length(p)-s;
}
//float sdBox( float3 p, float3 b )
//{
// float3 q = abs(p) - b;
// return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);
//}
//float sdTorus( float3 p, float2 t )
//{
// float2 q = float2(length(float2(p.x,p.z))-t.x,p.y);
// return length(q)-t.y;
//}
float sdCapsule2( float3 a, float3 b, float r )
{
float3 BA = a - b ;
float h = clamp(dot(a, BA) / dot(BA, BA),0.0,1.0);
return length(a- BA* h) - r;
}
float sdCapsuleBODY(float3 a, float3 b, float R )
{
float3 BA = a-b;
float h = clamp(dot(a, BA) / dot(BA, BA),0.0,1.0);
float X3 = h * h * h ;
float X4 = X3 * h ;
float X5 = X4 * h ;
float X6 = X5 * h ;
float X7 = X6 * h ;
float X8 = X7 * h ;
// 'https://www.desmos.com/calculator/rht0mu9d8s
float F = X8 - 4.0 * X7 + 6.0 * X6 - 3.0 * X5 - X4 + X3 ;
return length(a- BA * h) - R - (F * 52.0 - 0.5) * R * 0.3;
}
float sdCapsuleLEG(float3 a , float3 b , float R )
{
float3 BA = a - b ;
float h = clamp(dot (a, BA) / dot(BA, BA),0.0,1.0) ;
float X = 1.57 + h * h * 6.28;
while (X > 3.14) X = X - 6.28 ;
//while (X < -3.14) X = X + 6.28 ;
float X2 = X * X ;
float X3 = X2 * X ;
float X4 = X3 * X ;
float X5 = X4 * X ;
float X6 = X5 * X ;
//'(FASTSIN)
float F = (C12671_D_4363920 * X5 - C2363_D_18183 * X3 + X) /
(C121_D_16662240 * X6 + C601_D_872784 * X4 + C445_D_12122 * X2 + 1.0) ;
return length(a- BA * h) - R * 0.8 - F * R * 0.2 ;
}
float2 min2(float2 a,float2 b)
{
if (a.x < b.x)
{ return a; } else
{ return b; }
}
float2 minCubic2(float2 a, float2 b , float K )
{
float2 r;
float h = max(K - abs(a.x - b.x), 0.0) / K ;
r.x = min(a.x, b.x) - h * h * h * K * 0.16667 ; // '(1# / 6#)
if (a.x < b.x) r.y = a.y; else r.y = b.y ;
return r;
}
/////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
float hash(float n)
{
float p = frac(n * 0.1031) ;
p = p * p + 33.33 ;
p = p * p + p ;
return frac(p);
}
float noise3(float3 x) {
float3 p = floor(x);
float3 f = frac(x);
f = f * f * (3.0 - 2.0 * f);
float n = p.x + p.y * 157.0 + 113.0 * p.z;
return lerp(
lerp(lerp(hash(n + 0.0), hash(n + 1.0), f.x),
lerp(hash(n + 157.0), hash(n + 158.0), f.x), f.y),
lerp(lerp(hash(n + 113.0), hash(n + 114.0), f.x),
lerp(hash(n + 270.0), hash(n + 271.0), f.x), f.y), f.z);
}
//float fbm(float3 p) {
// float f = 0.0;
// f = 0.5000 * noise3(p);
// p *= 2.01;
// f += 0.2500 * noise3(p);
// p *= 2.02;
// f += 0.1250 * noise3(p);
// return f;
//}
float fbm32( float3 x)
{
float G = 0.574 ; // exp2(-0.8); // = 2^-0.8
//float G = exp2(-0.8);
float f = 1.0;
float a = 1.0;
float t = 0.0;
for( int i=0; i<3; i++ )
{
t += a*noise3(f*x);
f *= 2.0;
a *= G;
}
return t;
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////// Get DISTANCE of a point
float2 SCENE(float3 pos){
float sizeleg=2.5;
float3 mfloor =pos;
//pos=Repeat3(pos, float3(256.0, 0.0, 256.0), (P1+P2[i])*0.5) ;
float2 d = float2 (9999.0,0.0);
float3 mydire;
float3 lat ;
float3 lat1;
float3 lat2;
float3 hup;
for (int i=0; i<NCRE; i++) {
mydire = normalize(P2[i]-P1[i]);
lat = cross(mydire, float3(0, 1, 0)) *sizeleg * 1.0;
lat1=lat+float3(0,sizeleg,0);
lat2=-lat+float3(0,sizeleg,0);
hup= cross(normalize(lat),mydire);
// Legs
d=min2(d,float2(sdCapsule2(pos-P1[i]+lat1,pos-P3[i],sizeleg),1.0)) ;
d=min2(d,float2(sdCapsuleLEG(pos-P3[i],pos-P4[i],sizeleg),1.0)) ;
d=min2(d,float2(sdCapsule2(pos-P1[i]+lat2,pos-P5[i],sizeleg),1.0)) ;
d=min2(d,float2(sdCapsuleLEG(pos-P5[i],pos-P6[i],sizeleg),1.0)) ;
d=min2(d,float2(sdCapsule2(pos-P2[i]+lat1,pos-P7[i],sizeleg),1.0)) ;
d=min2(d,float2(sdCapsuleLEG(pos-P7[i],pos-P8[i],sizeleg),1.0)) ;
d=min2(d,float2(sdCapsule2(pos-P2[i]+lat2,pos-P9[i],sizeleg),1.0)) ;
d=min2(d,float2(sdCapsuleLEG(pos-P9[i],pos-P0[i],sizeleg),1.0)) ;
//HEAD
d=min2(d,float2(sdSphere(pos-P2[i]-mydire*6.5-hup*4.5,sizeleg*3.0-0.5),1.1)) ; // 1.0
// BODY
d= minCubic2(d,float2(sdCapsuleBODY(pos-P1[i],pos-P2[i],5), 1.0),3.0); //3.5
}
// TERRAIN
// float T1=noise3(float3(mfloor.x * 0.021 , mfloor.z*0.023 , 1.0));
// T1 = T1 * T1 * T1 * 5.7 ;
float T2 = noise3(float3(mfloor.x * 0.0052, mfloor.z * 0.0049, 1.0)) ;
T2 = T2 * T2 * 60.0;
float T3 = noise3(float3(mfloor.x * 0.0011, mfloor.z * 0.0013, 1.0)) ;
T3 = T3 * T3 * T3 *120.0;
d = min2(d,float2(mfloor.y+sizeleg - T2 - T3 , 0.0));
return d;
}
///////////////////////////////////////// Marching Ray
float2 RayMarch (float3 ro, float3 rd )
{ float t = 0.1;
float2 d0 =float2(0,0) ;
for (int i=0; i < MAXSTEPS; i++) {
d0 = SCENE(ro + rd * t) ;
t = t + d0.x;
if (t > MAX_DIST ) i=MAXSTEPS ;
if (abs(d0.x )< EPS) i=MAXSTEPS ;
}
if (t > MAX_DIST) t= -1.0 ;
return float2(t,d0.y) ;
}
//////////////////////////////////////// Compute SCENE Normal
float3 CalcSceneNormal(float3 p) {
float3 vn1 =float3( 1.0, -1.0, -1.0);
float3 vn2 =float3(-1.0, -1.0, 1.0);
float3 vn3 =float3(-1.0, 1.0, -1.0);
float3 vn4 =float3( 1.0, 1.0, 1.0);
float3 r1 = vn1 * SCENE(p + vn1 * EPS).x;
float3 r2 = vn2 * SCENE(p + vn2 * EPS).x;
float3 r3 = vn3 * SCENE(p + vn3 * EPS).x;
float3 r4 = vn4 * SCENE(p + vn4 * EPS).x;
return normalize(r1 + r2 + r3 + r4 );
}
float CalcSOFTShadow(float3 Ro ,float3 Rd , float K, float tMIN )
{
float tMax = 400 ;//' maxD * 0.5 // '* 1.5 ''<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
float res = 1.0;
float T = tMIN;
float h = 0.0;
float tRes = 0.0;
while ( T < tMax) {
h = SCENE(Ro + Rd * T).x ;
//if h < 0.0 Then h = 0.0: res = 0: Exit Do
if (h < 0.0) T=tMax;//break;
tRes = K * h / T ;
if (tRes < res) res = tRes ;
if (h < EPS) T=tMax;//break;
T = T + h;
}
return smoothstep(0.0,1.0,res);
}
/////////////////////////////////////////// BASIC LIGHTING
float3 applyFog(float3 RGB , float distance , float DotSunDirRayDir )
{
//https://www.iquilezles.org/www/articles/fog/fog.htm
float fogAmount = 1.0- exp(-distance * 0.00038) ;
//float fogAmount = 1.0- pow(2.7,-distance * 0.00038) ;
float3 fogColor=float3(0,0,0);
if (DotSunDirRayDir > 0.0) {
float sunAmount = pow(DotSunDirRayDir,8.0) ;
fogColor = float3(lerp(0.5,1.0,sunAmount) ,
lerp(0.6,0.9,sunAmount) ,
lerp(0.7,0.6,sunAmount) ) ;
// fogColor = lerp3(float3(0.5, 0.6, 0.7), float3(1#, 0.9, 0.7), sunAmount ^ 8#)
}
else
{ fogColor = float3(0.5, 0.6, 0.7); }
// applyFog = Mix3(RGB, fogColor, fogAmount)
return RGB*(1.0-fogAmount) + fogColor * fogAmount;
}
float3 lighting(float3 col , float3 POS , float3 nor , float3 Rd , float Dist )
{
// float amb = 0.01;
// float bac = 0.01;
float dif = clamp(dot(SunLight, nor),0.0 , 1.0) ;
float3 ref = reflect(SunLight, nor) ;
float spec = clamp(dot(Rd, ref),0.0,1.0) ; //Specular Shiness
float SHA = dif ;
//if (dif > 0.0) SHA = SHA * CalcSOFTShadow(POS + (nor * EPS), SunLight, 9.0, 5.0) ;
if (dif > 0.0) SHA = SHA * CalcSOFTShadow(POS + (nor * EPS), SunLight, 14.0, 5.0) ;
// SHA = 0.05 + SHA * 0.95 ;
SHA = 0.1 + SHA * 0.9 ;
float3 lin = col * SHA ;
// lin = lin + float3(0.5, 0.5, 0.5) * amb ;
// lin = lin + float3(0.2, 0.2, 0.5) * bac ;
// SUN
lin = lin + float3(0.9, 0.9, 0.1)* (0.5 * SHA *SHA) ;
// SHINE
lin = lin + float3(0.5, 0.5, 1.0)* pow(1.0 * spec * SHA,8.0) ;
lin= applyFog(lin, Dist, dot(SunLight, Rd)) ;
return lin ;
}
float3 lighttoon(float3 col , float3 POS , float3 nor , float3 rd , float2 e )
{
float3 view = -rd ;
float3 amb=float3(0.05, 0.05, 0.05);
float dif = dot(SunLight,nor);
float3 h = normalize(SunLight - rd);
float spec = pow ( clamp(dot(nor,h), 0.0 ,1.0) , 25.0 );
float edge = clamp(dot(nor,view), 0.0 ,1.0);
edge = smoothstep(e.x, e.y, edge) ; // 0.4 0.75
//float edge = 1.0 ; // NO EDGE
dif = 0.65 + 0.35 * dif ; // dif รจ anche negativo
//float sun = 0.5 + 0.5 * clamp(dot(view,SunLight), 0.0 ,1.0);
float sun = 0.25 + 0.75 * clamp(dot(view,SunLight), 0.0 ,1.0);
float SHA = CalcSOFTShadow(POS + nor * EPS, SunLight, 9.0, 5.0) ;
// SHA = CalcShadow( POS + nor * EPS, SunLight, 2.0) ;
dif = dif * (0.4 + 0.6 * SHA) ;
spec = spec * SHA ;
return amb + col * ( (dif + spec) * (pow(sun,0.25) * edge) ) ;
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
float4 ps_main(VS_Output input) : COLOR0
{
// return mytexture.Sample(mysampler, input.uv);
float4 col4=float4(0.0,0.0,0.0,1.0);
float2 UV = input.uv;
// UV=UV*2-1;
// UV.y=-UV.y;
SunLight = normalize (float3(1.0,0.65,1.0)) ;
///////////////// Minimal Camera
//float3 ro = float3(0.0, 1.2, 0.0);
//float3 rd = normalize(float3 ( UV.x, UV.y, 1.0) );
float3 ro = CAMPOS;
float3 ww = normalize(CAMLOOKAT - CAMPOS);
float3 uu = normalize(cross(ww, float3(0.0,-1.0,0.0)));
float3 vv = normalize(cross(ww, uu));
float3 rd = normalize(uu*UV.x + vv*UV.y + ww*1.55 ); //ww =zoom
float3 col ; // = float3(0.0,0.0,0.0);
float2 d = RayMarch(ro , rd ) ;
float2 edge ;
if (d.y > 0.0)
{
col = float3(0.65,0.3,0.1) ; // CREATURE COLOR
edge = float2( 0.25, 0.5) ;
}
else
{
col = float3(0.36, 0.4, 0.15);
edge = float2( 0.0, 0.15) ;
} ;
//d=d*.001; return float4(d,d,d ,1.0);
if (d.x >0.0)
{
float3 TouchLocation = ro + rd * d.x ;
float3 nor = CalcSceneNormal(TouchLocation);
col = lighting (col , TouchLocation, nor, rd , d.x);
// col = lighttoon (col , TouchLocation, nor, rd , edge );
}
else
{
//////////////////////////////////// SKY
////////////////////////////////////
col = float3(0.1, 0.1, 1) - rd.y * rd.y * 5.0;
col = lerp(col, float3(0.3, 0.6, 1)* 0.5, pow(1.0-min(rd.y, 0.0) ,4.0));
float SunDOT = clamp(dot(rd, SunLight),0.0,1.0);
// clouds
float2 SC = float2(CAMPOS.x, CAMPOS.z);
if (rd.y > 0.0) {
SC = SC + float2(rd.x, rd.z) *
( 700.0 - CAMPOS.y) / rd.y;
//SC=SC+float2(MyTime*50.0,MyTime*23.0);
col = lerp(col,
float3(1.0, 0.95, 1.0), 1.0 - 0.9 * smoothstep(0.5, 0.75,
fbm32(float3(SC.x, SC.y, 1.0)*0.0008 ) ) );
col = lerp(col, float3(0, 0.2, 0.4), pow(1.0 - rd.y , 8.0));
col = col + float3(1.0, 0.75, 0.1)* 1.0 * pow(SunDOT, 10.0);
}
float FogSKY = (1.0 - rd.y * 4.75) ;
if (FogSKY > 0.0) col = applyFog(col, FogSKY * FogSKY * FogSKY * MAX_DIST, SunDOT) ;
//////////////////////////////////// fine SKY
}
col4 = float4(col.x,col.y,col.z,1.0);
return col4;
}
/////////////////////////////////////
//// intrinsic FUNCTIONS
/////////////////////////////////////
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-intrinsic-functions
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
About TheTrick DX9
I have noticed that there are often problems compiling the HLSL shader, especially if it is complex.
Sometimes it takes several minutes.
To get around this problem I discovered that in the function D3DXCompileShaderFromFile
there is a very useful option, that is to use FLAGS
So, if you are testing a shader, modifying it frequently to see the results I suggest to use the following Flags so that the compilation will take few seconds.
' FLAGS -----------------------------------------------------------------
' https://docs.microsoft.com/en-us/win...dxshader-flags
' &H1000 D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
' &H4000 D3DXSHADER_OPTIMIZATION_LEVEL0
' &H20 D3DXSHADER_PARTIALPRECISION
Code:
' // Compile pixel shader code
hr = D3DXCompileShaderFromFile(StrPtr(FN), ByVal 0&, Nothing, "ps_main", _
StrPtr(StrConv("ps_3_0", vbFromUnicode)), _
&H1000 Or &H4000 Or &H20, cPSCode, cErrMsg, cPSConstTbl)
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
hi TheTrick
As far as RayMarching is concerned I am now at a very good point.
I would like to talk/develop the second topic here.
Here is what it consists of:
1) Load a texture or byteArray rapresenting an image (RGB) or (RGBA) in VB6.
2) Pass this Texture to the Pixel/Fragment Shader.
3) Process it. Apply some image-filter by using PixelShader via HLSL.
(The modification will be done using a new texture or the output of PS itself)
4) Get back the result to VB6 as Texutre or ByteArray.
In this example video you can see one that did it [ https://www.youtube.com/watch?v=UxuFidrukgQ ]
Using GPU via HLSL to perform a graphic effect should be immensely faster than using CPU.
EDIT:
Good resources can be found on github (even if they are in GLSL)
But what I don't know is how to pass the Texture and get the processed result back.
https://github.com/yulu/ShaderFilter
https://github.com/yulu/GLtext
https://github.com/search?q=shader+image+processing
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
I'll answer later because i have a lot of projects right now which i need to complete. There are the several examples where i used texture check them out.
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Hi TheTrick, don't worry, I understand.
Here is an example of Image Processing using HLSL.
[ DOWNLOAD ALL ]
This version is dynamic (uses timers), but that's just for this demo.
I made some not very significant effects, just to experiment.
https://www.vbforums.com/images/ieimages/2021/02/1.jpg
Questions:
1 - How to get the (displayed) output Bytes of the modified image (texture) ? [This of course regarding a "static" image taken at a given time].
2 - Is it possible to send a Texture without loading it from a file ? That is, using an array of Bytes present in VB6?
Ok, these for the moment are the main questions.
When you have time I hope to have some answers. (by the way, anyone interested who knows something is kindly requested to speak)
One last thing, I would like (as I did) to use a DX Class in order to have a sort of reusability.
(EG: not all in one vbForm).
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
maybe dx11,3d,you need use vc,vc++
Perhaps python will be more convenient in the future.
it'S suport websocket ,ws,wss ,opencv 。
In China, we have removed vb6 from the computer rank examination,The Python programming language has been used for many years.
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
using an array of Bytes present in VB6?
it'S only pointer like:
public BT(10000) aS byte
ptr=varptr(BT(0))
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Quote:
Originally Posted by
reexre
Questions:
1 - How to get the (displayed) output Bytes of the modified image (texture) ? [This of course regarding a "static" image taken at a given time].
2 - Is it possible to send a Texture without loading it from a file ? That is, using an array of Bytes present in VB6?
Ok, these for the moment are the main questions.
When you have time I hope to have some answers. (by the way, anyone interested who knows something is kindly requested to speak)
One last thing, I would like (as I did) to use a DX Class in order to have a sort of reusability.
(EG: not all in one vbForm).
Can TheTrick or someone else please help me?
I have searched the internet extensively but have not found any solutions.
The 1st question is difficult and I think it has two ways of solution.
1 - Copy the output of the DX-Device to a texure and get it with Device.GetTexture. (and then get the bytes of the texture)
2 - Get the output of the DX-Device as bytes/image/picture directly with some other system.
Regarding the question 2nd
I think we have to use GdiPlus of which I know almost anything including hImage, hbitmap GdipCreateFromHDC hGraphic _GDIPlus_BitmapCreateFromHBITMAP
For someone familiar with GdiPlus it should not be difficult to create a DirectX texture from a Picture or ByteArray.
( code to start from https://github.com/miorsoft/VB6-HLSL...rocessing%2000 )
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
@reexre,
please pay attention to this example. It shows how to pass the texture between GDI/Direct3D. This example shows how to extract the data from Direct3D rendering result to GDI+/GDI.
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Quote:
Originally Posted by
The trick
@reexre,
please pay attention to
this example. It shows how to pass the texture between GDI/Direct3D.
This example shows how to extract the data from Direct3D rendering result to GDI+/GDI.
thank you I will
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Ok I was able to set the DX texture from a vb picturebox.
Code:
Public Sub TextureFromPictureBox(PIC_hDC As Long, PIC_hWnd&, PIC_W As Long, PIC_H As Long)
Dim tmpDC As Long
Dim oldBmp As Long
Dim rect As D3DLOCKED_RECT
Dim delta As Long
Dim lpDat As Long
biWnd.bmiHeader.biSize = Len(biWnd.bmiHeader)
biWnd.bmiHeader.biBitCount = 32
biWnd.bmiHeader.biHeight = -PIC_H '-Me.Height / Screen.TwipsPerPixelY
biWnd.bmiHeader.biWidth = PIC_W 'Me.Width / Screen.TwipsPerPixelY
biWnd.bmiHeader.biPlanes = 1
bmpShadow = CreateDIBSection(PIC_hDC, biWnd, 0, lpBmpData, 0, 0)
m_cDevice.CreateTexture biWnd.bmiHeader.biWidth, -biWnd.bmiHeader.biHeight, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, m_cTexture
' // Create the bitmap with the contents of window
tmpDC = CreateCompatibleDC(PIC_hDC)
oldBmp = SelectObject(tmpDC, bmpShadow)
PrintWindow PIC_hWnd, tmpDC, 0
SelectObject tmpDC, oldBmp
DeleteDC tmpDC
' // Move data from the bitmap to the m_cTexture
m_cTexture.LockRect 0, rect, ByVal 0&, 0
lpDat = lpBmpData
' // Copy each scan-line
For delta = 0 To (-biWnd.bmiHeader.biHeight) - 1
memcpy ByVal rect.pBits, ByVal lpDat, biWnd.bmiHeader.biWidth * 4
rect.pBits = rect.pBits + rect.Pitch
lpDat = lpDat + biWnd.bmiHeader.biWidth * 4
Next
m_cTexture.UnlockRect 0
m_cDevice.SetTexture 0, m_cTexture
Dim V As D3DVECTOR
V.X = biWnd.bmiHeader.biWidth
V.Y = -biWnd.bmiHeader.biHeight
Me.SetVariableFloat3 Me.getRegisterNum("texRes"), V
End Sub
[ There is probably something "redundant" in this code (although it works). Which I don't know how it could be simplified. Because it was "extracted" from code used to create a texture from a Window (not a picturebox). ]
Now, in addition to the other question, it remains how to set a texture from a bytearray.
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
I came up with an extremely easy way to set a DX-texture from a ByteArray.
In this case the ByteArray width is 4 times the width of the image, each value represents the colors B G R A.
The origin coordinate is (0,0) [not (1,1)].
EG before calling BytesArrayToTexture
Code:
W = 127 : H = 127 : ReDim BGRA((W + 1) * 4 - 1, H) 'ReDim BGRA(W * 4 + 3, H)
For X = 0 To W
For Y = 0 To H
BGRA(X * 4 + 0, Y) = 255
BGRA(X * 4 + 1, Y) = X * 255 / W
BGRA(X * 4 + 2, Y) = Y * 255 / H
BGRA(X * 4 + 3, Y) = 255
Next
Next
Code:
Public Sub BytesArrayToTexture(BGRA() As Byte, TextureSamplerDest As Long)
' BGRA = Bytes array (Width is 4x)
Dim rect As D3DLOCKED_RECT
Dim DXtexture As IDirect3DTexture9
Dim W&, H&, Nbytes&
W = UBound(BGRA, 1)
H = UBound(BGRA, 2)
Nbytes = (W + 1) * (H + 1)
m_cDevice.CreateTexture (W + 1) \ 4, H + 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, DXtexture
DXtexture.LockRect 0, rect, ByVal 0&, 0
memcpy ByVal rect.pBits, BGRA(0, 0), Nbytes
DXtexture.UnlockRect 0
m_cDevice.SetTexture TextureSamplerDest, DXtexture
End Sub
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Using the code above as a starting point, and with some research , here is the code to get the output of the DX device as a ByteArray.
I haven't tested it well yet and I'm not sure if it works correctly yet.
More information will follow.
Suggestions are of course welcome.
Code:
Public Sub GetDeviceOutAsBytes(OUT() As Byte)
Dim RECT As D3DLOCKED_RECT
Dim SRF As IDirect3DSurface9
Dim W&, H&, Nbytes&
' Dim pp As D3DDEVICE_CREATION_PARAMETERS
' Dim wr As twRECT
' m_cDevice.GetCreationParameters pp
' GetClientRect pp.hFocusWindow, wr
' W = (wr.Right - wr.Left) * 4 - 1
' H = wr.Bottom - wr.Top - 1
W = m_WW * 4 - 1
H = m_HH - 1
ReDim OUT(W, H)
Nbytes = (W + 1) * (H + 1)
m_cDevice.CreateOffscreenPlainSurface (W + 1) \ 4, H + 1, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, SRF
m_cDevice.GetRenderTargetData m_cDevice.GetRenderTarget(0), SRF
SRF.LockRect RECT, ByVal 0&, D3DLOCK_READONLY
memcpy OUT(0, 0), ByVal RECT.pBits, Nbytes
SRF.UnlockRect
End Sub
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
I am planning to deploy an application that uses the last technique shown.
1) What DX version will the user need on his system? (Will a version higher than 9 work?)
2) Will it be sufficient to put dx9vb.tbl and d3dxvb.tbl in the root directory of the program?
3) How to make sure (algorithm/function) that the user's system has the necessary characteristics to work? (and if not, show an appropriate message to the user)
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Quote:
Originally Posted by
reexre
2) Will it be sufficient to put dx9vb.tbl and d3dxvb.tbl in the root directory of the program?
No, you don't distribute .tlb files to end users at all. You need these registered on your development machine only.
cheers,
</wqw>
-
Re: RAYMARCHING HLSL/GLSL (DX/OpenGL)
Quote:
Originally Posted by
reexre
1) What DX version will the user need on his system? (Will a version higher than 9 work?)
DirectX9 and higher (installed by default).
Quote:
Originally Posted by
reexre
2) Will it be sufficient to put dx9vb.tbl and d3dxvb.tbl in the root directory of the program?
You don't need to redistribute tlb at all. A single executable is enough. If you use d3dx9_xx.dll it should be reditributed.
Quote:
Originally Posted by
reexre
3) How to make sure (algorithm/function) that the user's system has the necessary characteristics to work? (and if not, show an appropriate message to the user)
What's exectly functions? IDirect3D9::GetDeviceCaps https://docs.microsoft.com/en-us/win...per-idirect3d9