Does It possible to make light-point for a Scene from HLSL shader?

Problems building or running the engine, queries about how to use features etc.
vincentdoan86
Gnoblar
Posts: 7
Joined: Wed May 31, 2023 4:11 am

Does It possible to make light-point for a Scene from HLSL shader?

Post by vincentdoan86 »

I want to ask everyone, in a scene without a lighting system to illuminate the scene like AmbientColor, Light Diffuse, or Light specular, can a shader create a lighting effect for the whole scene? Does anyone have any examples that can help me in this case, or a tutorial to be able to write this type of shader? My game engine uses direct3d 9 and old Ogre3d 1.7 and it is closed source, cannot be modified, so I hope shaders can help a little.

paroj
OGRE Team Member
OGRE Team Member
Posts: 2087
Joined: Sun Mar 30, 2014 2:51 pm
x 1127

Re: Does It possible to make light-point for a Scene from HLSL shader?

Post by paroj »

yes, you can create a whole scene using shaders. see e.g. https://www.shadertoy.com/view/MdjGR1

However, you need to be confident with math to make it work correctly, especially when parts of the scene come from Ogre.

vincentdoan86
Gnoblar
Posts: 7
Joined: Wed May 31, 2023 4:11 am

Re: Does It possible to make light-point for a Scene from HLSL shader?

Post by vincentdoan86 »

I don't need to create the whole scene with shaders, I just want to create the lighting for the space in the scene from shader code so that I can adjust it with shaders from outside without interfering with the source code of ogre3d or direct3d. I already have a game engine from the combination of ogre3d and direct3d. I can load the scene, and also have fixed light sources. But I want to create an external light source with shaders so that I can conveniently adjust the space in the scene to be bright or dark as I want. So do you have any examples or tutorials, because I have just learned about shaders not long ago.

rpgplayerrobin
Gnoll
Posts: 656
Joined: Wed Mar 18, 2009 3:03 am
x 370

Re: Does It possible to make light-point for a Scene from HLSL shader?

Post by rpgplayerrobin »

If you do not have any access to the source code, and you want to hardcode lights in the hlsl shader, this has nothing to do with Ogre.
But I could try to help you anyway if you have a shader that you can share.

Note that if you do it this way, you would have to do the same change for all shaders in the game, otherwise lights would not affect all objects.
And all lights would have to be calculated in world-space and not object-space, otherwise it will be impossible to hardcode the lights in an easy way for all shaders.

Also, note that if you need shadows for the lights, that can be painful to do since it requires a texture to be rendered specifically from a shadow camera, so you cannot really get shadows with any lights you add unless you do the shadows completely in HLSL (which would most likely be extremely slow compared to normal shadowmaps, and I would not even know where to start regarding that).

Again, we would need a shader in order to help you. But I would also ask you to first post the shader to ChatGPT and tell it exactly this:

Can you modify this shader to support 5 hardcoded lights, that I can myself hardcode values of in the shader? I want it to have multiple variables per light: World position, Diffuse color, Specular color and Attenuation:
YOUR SHADER CODE HERE

vincentdoan86
Gnoblar
Posts: 7
Joined: Wed May 31, 2023 4:11 am

Re: Does It possible to make light-point for a Scene from HLSL shader?

Post by vincentdoan86 »

So here is my shader. In my shader I tried to render the lights from loading it into sky material. In my scene, I had a skybox with meshes and loaidng texture material. If I had nothing wrong, the shader that I loaded by sky texture will render just on the surface of that texture right. But I want to loadthe lights into world space to light up the scene, I do not need any shadow for the objects in the scene, I just want to make lights in the scene and control all the lights from shader. The game engine that I had, It is already load the light into the scene, but it is default light effect system that ogre3d rendered and could not change into light or dark effect for scene.

can you guys help me to check, fix,or give me some Ideas to make It work. I really appreciate you guys.

Code: Select all

float4x4 World;
float4x4 View;
float4x4 Projection;
float4 CameraPosition;

// Light 1 properties
float4 Light1Position = float4(0.0, 10.0, 0.0, 1.0);     // World position of Light 1
float4 Light1Diffuse = float4(0.921569, 0.639216, 0.211765, 1.0); // Diffuse color of Light 1
float4 Light1Specular = float4(0.184314, 0.368627, 0.360784, 1.0); // Specular color of Light 1
float Light1Attenuation = 0.1; // Attenuation factor of Light 1

// Light 2 properties
float4 Light2Position = float4(5.0, 10.0, 0.0, 1.0);     // World position of Light 2
float4 Light2Diffuse = float4(0.203922, 0.156863, 0.647059, 1.0); // Diffuse color of Light 2
float4 Light2Specular = float4(0.184314, 0.368627, 0.360784, 1.0); // Specular color of Light 2
float Light2Attenuation = 0.2; // Attenuation factor of Light 2

// Light 3 properties
float4 Light3Position = float4(-5.0, 10.0, 0.0, 1.0);    // World position of Light 3
float4 Light3Diffuse = float4(0.5, 0.8, 0.3, 1.0);       // Diffuse color of Light 3
float4 Light3Specular = float4(0.2, 0.6, 0.8, 1.0);      // Specular color of Light 3
float Light3Attenuation = 0.15; // Attenuation factor of Light 3

// Light 4 properties
float4 Light4Position = float4(0.0, 15.0, 5.0, 1.0);     // World position of Light 4
float4 Light4Diffuse = float4(0.7, 0.1, 0.2, 1.0);       // Diffuse color of Light 4
float4 Light4Specular = float4(0.9, 0.3, 0.4, 1.0);      // Specular color of Light 4
float Light4Attenuation = 0.05; // Attenuation factor of Light 4

// Light 5 properties
float4 Light5Position = float4(-5.0, 15.0, 5.0, 1.0);    // World position of Light 5
float4 Light5Diffuse = float4(0.2, 0.5, 0.7, 1.0);       // Diffuse color of Light 5
float4 Light5Specular = float4(0.4, 0.2, 0.5, 1.0);      // Specular color of Light 5
float Light5Attenuation = 0.25; // Attenuation factor of Light 5

sampler2D baseTexture : register(s0);

struct VS_IN
{
    float4 inPos : POSITION;
    float3 inNormal : NORMAL;
};

struct VS_OUT
{
    float4 Position : POSITION;   // Transformed position
    float3 WorldPos : TEXCOORD0;  // World space position
    float3 Normal : TEXCOORD1;    // World space normal
};

// Function to calculate the lighting contribution from a single light
float3 calculateLight(float3 normal, float3 lightPos, float3 lightDiffuse, float3 lightSpecular, float3 fragPos, float3 viewDir, float attenuation)
{
    float3 lightDir = normalize(lightPos - fragPos);
    float distance = length(lightPos - fragPos);
    float attenuationFactor = 1.0 / (1.0 + attenuation * distance * distance);

// Diffuse shading
float diffuseFactor = max(dot(normal, lightDir), 0.0);
float3 diffuse = lightDiffuse * diffuseFactor * attenuationFactor;

// Specular shading
float3 reflectDir = reflect(-lightDir, normal);
float specularFactor = pow(max(dot(viewDir, reflectDir), 0.0), 32);
float3 specular = lightSpecular * specularFactor * attenuationFactor;

return diffuse + specular;
}

VS_OUT mainVS(VS_IN input)
{
    VS_OUT output;

// Transform vertex position to world space
float4 worldPos = mul(World, input.inPos);
output.WorldPos = worldPos.xyz;

// Transform normal to world space
output.Normal = mul((float3x3)World, input.inNormal);

// Transform position to clip space
output.Position = mul(mul(View, Projection), worldPos);

return output;
}

float4 mainPS(VS_OUT input) : COLOR
{
    // Normalize normal vector
    float3 normal = normalize(input.Normal);

// Calculate view direction
float3 viewDir = normalize(CameraPosition.xyz - input.WorldPos);

// Accumulate lighting contributions from all 5 lights
float3 lighting = float3(0.0, 0.0, 0.0);
lighting += calculateLight(normal, Light1Position.xyz, Light1Diffuse.xyz, Light1Specular.xyz, input.WorldPos, viewDir, Light1Attenuation);
lighting += calculateLight(normal, Light2Position.xyz, Light2Diffuse.xyz, Light2Specular.xyz, input.WorldPos, viewDir, Light2Attenuation);
lighting += calculateLight(normal, Light3Position.xyz, Light3Diffuse.xyz, Light3Specular.xyz, input.WorldPos, viewDir, Light3Attenuation);
lighting += calculateLight(normal, Light4Position.xyz, Light4Diffuse.xyz, Light4Specular.xyz, input.WorldPos, viewDir, Light4Attenuation);
lighting += calculateLight(normal, Light5Position.xyz, Light5Diffuse.xyz, Light5Specular.xyz, input.WorldPos, viewDir, Light5Attenuation);

// Add ambient light
float4 ambient = tex2D(baseTexture, float2(0.5, 0.5)) * 0.1;
float4 finalColor = float4(lighting, 1.0) + ambient;

return finalColor;
}
rpgplayerrobin
Gnoll
Posts: 656
Joined: Wed Mar 18, 2009 3:03 am
x 370

Re: Does It possible to make light-point for a Scene from HLSL shader?

Post by rpgplayerrobin »

In my shader I tried to render the lights from loading it into sky material. In my scene, I had a skybox with meshes and loaidng texture material. If I had nothing wrong, the shader that I loaded by sky texture will render just on the surface of that texture right.

What does that mean exactly? The shader is supposed to be on the meshes being rendered, not on the sky.

But I want to loadthe lights into world space to light up the scene, I do not need any shadow for the objects in the scene, I just want to make lights in the scene and control all the lights from shader. The game engine that I had, It is already load the light into the scene, but it is default light effect system that ogre3d rendered and could not change into light or dark effect for scene.

So in short, you don't have access to the code, but the code itself already has lights in the scene. You simply want to use those existing lights on these new shaders? In that case, instead of this (and all other lights):

Code: Select all

// Light 1 properties
float4 Light1Position = float4(0.0, 10.0, 0.0, 1.0);     // World position of Light 1
float4 Light1Diffuse = float4(0.921569, 0.639216, 0.211765, 1.0); // Diffuse color of Light 1
float4 Light1Specular = float4(0.184314, 0.368627, 0.360784, 1.0); // Specular color of Light 1
float Light1Attenuation = 0.1; // Attenuation factor of Light 1

Do this:

Code: Select all

// Light 1 properties
float4 Light1Position;     // World position of Light 1
float4 Light1Diffuse; // Diffuse color of Light 1
float4 Light1Specular; // Specular color of Light 1
float4 Light1Attenuation; // Attenuation factor of Light 1

And then add this to the shader material:

Code: Select all

param_named_auto Light1Diffuse light_diffuse_colour 0
param_named_auto Light1Specular light_specular_colour 0
param_named_auto Light1Attenuation light_attenuation 0
param_named_auto Light1Position light_position 0

If you want another light (or more), simply copy paste the code above and rename them to 2 in their name and then change the last 0 to a 1.

The above code assumes point lights, but you can get spotlights and directional lights to also work if you wanted to, if you are even using that in your pre-existing code base.

Note that the Light1Attenuation is now a float4, and you can handle it like this:

Code: Select all

float computeAttenuation( float3 vertexposition, float3 lightposition,
				   float4 attenuation )
{
	float d = distance( vertexposition, lightposition );
	return 1/(attenuation.y + attenuation.z * d + attenuation.w * d * d);
}

If you need help implementing it, simply ask ChatGPT to do it, it will most likely understand where to use it (multiply it to the added diffuse and specular of the light).

vincentdoan86
Gnoblar
Posts: 7
Joined: Wed May 31, 2023 4:11 am

Re: Does It possible to make light-point for a Scene from HLSL shader?

Post by vincentdoan86 »

In my scene there is a fixed light source called into the scene XML file as below:

Code: Select all

<Object name="#FairyEnviroment" type="Enviroment">
    <Property name="ambient" value="0.129412 0.34902 0.431373"/>
    <Property name="fog.mode" value="linear"/>
    <Property name="fog.colour" value="0.223672 0.659523 0.983757"/>
    <Property name="fog.linear start" value="3500"/>
    <Property name="fog.linear end" value="8378.18"/>
  </Object>

  <Object name="#FairyMainLightOne" type="Light">
    <Property name="type" value="directional"/>
    <Property name="diffuse" value="1 0.741176 0.258824"/>
    <Property name="specular" value="0.506496 0.327558 0.0312728"/>
    <Property name="direction" value="-0.2 -0.5 -0.4"/>
    <Property name="cast shadows" value="true"/>
  </Object>

  <Object name="#FairyMainLightTwo" type="Light">
    <Property name="type" value="directional"/>
    <Property name="diffuse" value="0.154952 0.571694 0.173605"/>
    <Property name="direction" value="0.4 -0.2 0.2"/>
  </Object>

and then, when I use ogre3d's param_named_auto as below:

Code: Select all

fragment_program Fake_Point_Light_PS hlsl
{
	source Fake_Point_Light.hlsl
	entry_point mainPS
	target ps_3_0

default_params
{
	param_named_auto LightPosition light_position 0
    param_named_auto LightDiffuse light_diffuse_colour 0
    param_named_auto LightSpecular light_specular_colour 0
    param_named_auto LightAttenuation light_attenuation 0
    param_named_auto AmbientLight ambient_light_colour 0
    param_named_auto CameraPosition camera_position 0
    
}
}

So like you said above my scene has the light source itself, that the shader will get the light source as well as the color and effect from the light of the source in the scene right?

rpgplayerrobin
Gnoll
Posts: 656
Joined: Wed Mar 18, 2009 3:03 am
x 370

Re: Does It possible to make light-point for a Scene from HLSL shader?

Post by rpgplayerrobin »

Yes.

But you have to change the shader a bit since you are using 2x directional lights (not point lights) and you are apparently also using fog.
Ask ChatGPT to change the code from point light to directional lights and see if it works.

Fog is a bit easier.
In the shader material (for the fragment shader):

Code: Select all

param_named_auto fogColour fog_colour
param_named_auto fogParams fog_params

For the hlsl file where you define the variables above the main function:

Code: Select all

float4 fogColour;
float4 fogParams;

The fog code (in the bottom of the shader):

Code: Select all

float fogEnabled = fogParams.x; // x is expDensity, which holds whether or not it is enabled
float fogStart = fogParams.y;
float fogEnd = fogParams.z;
float distanceFromCamera = length(position); //position is the world 3D position of the pixel
float fogFactor = (1.0 - saturate((fogEnd - distanceFromCamera) / (fogEnd - fogStart))) * fogEnabled;
color.xyz = lerp(color.xyz, fogColour.xyz, fogFactor);

Of course, this does not at all handle other kind of material types, such as transparency, alpha rejection and a lot others.
It also needs adjustment for materials that use additive blending, since that will look ugly with the fog unless you alter the shader for it.