Ways to send variables/locations to entity shaders

Posted By: jumpman

Ways to send variables/locations to entity shaders - 08/07/18 06:16

Hello friends!

Anyone have any tricks to send as many vector positions from the entity to be read by shaders? I'm already using vecSkill41-60 for individual vectors. Are there any other ways/tricks I can use to send more vectors for shaders? I dont want global variables (_var), because that will change every shader.
Posted By: txesmi

Re: Ways to send variables/locations to entity shaders - 08/07/18 08:25

Hi,
materials point to their directX LPD3DXEFFECT struct. It has many methods to modify the static table of the effect.

Code:
LPD3DXEFFECT _fx = _mtl->d3deffect;
if (_fx == NULL)
   error("unable to retrieve the effect of a material");
float _f[4] = ...;
if(_fx->SetVector("customName", _f) != NULL) // see: SetFloat, SetVectorArray, SetMatrix, SetMatrixArray...
   error("unable to modify the static table of an effect");



https://docs.microsoft.com/en-us/windows/desktop/direct3d9/id3dxbaseeffect

Salud!
Posted By: jumpman

Re: Ways to send variables/locations to entity shaders - 08/07/18 13:39

Hi Txesmi, how do I use that snippet of code?

Where do I define/retrieve LPD3DXEFFECT ?

How would an entity set that custom float for their own material, but also be unique to that material like the vecSkill41?
Posted By: txesmi

Re: Ways to send variables/locations to entity shaders - 08/07/18 14:48

Hi,
you need to include windows.h, the definition is into d3d9.h

ENABLE_RENDER material flag lets you modify the render of each visible entity which has the material assigned.

(untested code)
Code:
#define skFloatArray     skill20

...

function evnMtl00 () {
	if (mtl->d3deffect == NULL) // no effect loaded?
		return 1; // do not render
	if (me == NULL) // not an actual entity?
		return 0; // render as it is
	LPD3DXEFFECT _fx = mtl->d3deffect;
	// fill a float array, or retrieve a pointer to an array from the entity skill or whatever
	float *_fArray = (float*)my->skFloatArray;
	_fx->SetVector("myFloats", _fArray);
	return 0;
}

MATERIAL *mtl00 = {
	event = evnMtl00;
	flags = ENABLE_RENDER;
}



This is only needed when each entity has its own values for the same variables.
Posted By: jumpman

Re: Ways to send variables/locations to entity shaders - 08/07/18 15:56

Hey txesmi thanks for helping me, I think thats what im going for, but i get a script crash in the event, I think its this line?:

float *_fArray = (float*)my->skFloatArray;

Posted By: jumpman

Re: Ways to send variables/locations to entity shaders - 08/07/18 16:03

If I go into my .FX file and I place this:

Code:
float4 myFloats;



The script will crash when the engine runs.

i can see this in the d3d9.h

Code:
STDMETHOD(SetVector)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector) PURE;



in the .fx file ive done this as well:

Code:
const float4 myFloats;



and the script still crashes in the material event
Posted By: txesmi

Re: Ways to send variables/locations to entity shaders - 08/07/18 16:13

It has to point to an actual array of floats. The example simply casts an skill to a pointer, but the skill has to be filled first in the entity initialization.

Code:
float4 *myFloatsArray = sys_malloc(sizeof(float) * 4); // only once!
my->skFloatArray = (var)myFloatsArray;
... // whenever you need to change the values
myFloatsArray[0] = (float)my->red / 255.0;
myFloatsArray[1] = (float)my->green / 255.0;
myFloatsArray[2] = (float)my->blu / 255.0;
myFloatsArray[3] = (float)my->lightrange;

Posted By: jumpman

Re: Ways to send variables/locations to entity shaders - 08/07/18 16:22

if i leave the game running, the material event function crashes with "too many functions!" as well!
Posted By: txesmi

Re: Ways to send variables/locations to entity shaders - 08/07/18 16:27

It sound pretty strange. Have you added any loop to the event?
Posted By: jumpman

Re: Ways to send variables/locations to entity shaders - 08/07/18 16:58

That was unrelated to your work, Im sorry, I had a wait(1); by mistake in the material event, which caused the functions to increase when i paused the game, forgive me.

Back on track, heres what Im doing at the top of my entity action:
Code:
Action tester_ent()

{
float4 *myFloatsArray = sys_malloc(sizeof(float) * 4); // only once!
my->skFloatArray = (var)myFloatsArray;

...


my.material = mtl_Hero;  //---------Assign the Hero shader


while(1)

// changing the variable
myFloatsArray[0] = (float)my.x+random(200)-random(200);
myFloatsArray[1] = (float)my.y+random(200)-random(200);
myFloatsArray[2] = (float)my.z+random(200)-random(200);
myFloatsArray[3] = (float)0;

wait(1);
}




Here is the material event:

Code:
hero_event()
{
...

if (mtl->d3deffect == NULL) // no effect loaded?
		return 1; // do not render
		
	if (me == NULL) // not an actual entity?
		return 0; // render as it is
		
	LPD3DXEFFECT _fx = mtl->d3deffect;
	
	float *_fArray = (float*)my->skFloatArray; // fill a float array, or retrieve a pointer to an array from the entity skill or whatever
	_fx->SetVector("myFloats", _fArray);
//	
	return 0;

}





Is that correct?

This all doesnt crash until i add myFloats to the .fx file
Posted By: txesmi

Re: Ways to send variables/locations to entity shaders - 08/07/18 17:20

The effect compiler errors are always described in a prompt window. It does never crash. I don't know what could be happening crazy

Here goes a complete and tested example of the very same
Code:
#include <acknex.h>
#include <windows.h>
#include <d3d9.h>

#define skFloatArray     skill20

function evnCamMtl () {
	if (mtl->d3deffect == NULL)
		return 1;
	if (me == NULL)
		return 0;
	if (my->skFloatArray == 0)
		return 0;
	LPD3DXEFFECT _fx = mtl->d3deffect;
	_fx->SetVector("myFloats", (float*)my->skFloatArray);
	return 0;
}

MATERIAL *mtlCam = {
	event = evnCamMtl;
	flags = ENABLE_RENDER;
	effect = "
		const float4x4 matWorldViewProj;
		
		float4 myFloats;
		
		void VS (
			in float4 inPos	: POSITION,
			out float4 outPos	: POSITION) {
				outPos = mul ( inPos, matWorldViewProj );
			}
		
		float4 PS () : COLOR0 {
			return myFloats;
		}
		
		technique tech {
			pass p0 {
				ZWriteEnable = True;
				AlphaBlendEnable = False;
				
				VertexShader = compile vs_3_0 VS();
				PixelShader  = compile ps_3_0 PS();
			}
		}	
	";
}

action actSphere () {
	float *_fV = sys_malloc(sizeof(float) * 4);
	memset(_fV, 0, sizeof(float) * 4);
	my->skFloatArray = (var)_fV;
	my->material = mtlCam;
	while (!key_esc) {
		_fV[0] = random(1);
		_fV[1] = random(1);
		_fV[2] = random(1);
		_fV[3] = random(1);
		wait(1);
	}
	
	sys_free(_fV);
	ent_remove(me);
}


void main () {
	wait(1);
	level_load ("");
	camera->x = -200;
	int _count = 0;
	for (; _count<5; _count+=1)
		ENTITY *_ent = ent_create(SPHERE_MDL, vector(0, _count*50, 0), actSphere);
	
	while (!key_esc) {
		camera->pan = ang(camera->pan - mickey.x * 0.2);
		camera->tilt = clamp(camera->tilt - mickey.y * 0.2, -90, 90);
		wait(1);
	}
	
	wait(1);
	sys_exit(NULL);
}

Posted By: Superku

Re: Ways to send variables/locations to entity shaders - 08/07/18 20:08

Personally I'd just use the entity skills and not bother with the memory management. In the event:

float floatArray[4];
floatArray[0] = my.skill10;
floatArray[1] = my.skill11;
floatArray[2] = my.skill12;
floatArray[3] = my.skill13;
_fx->SetVector("myFloats", floatArray);
Posted By: jumpman

Re: Ways to send variables/locations to entity shaders - 08/07/18 20:11

whats the advantage of that Superku?
Posted By: Superku

Re: Ways to send variables/locations to entity shaders - 08/07/18 20:39

No additional memory management. Currently, you need to sys_free the memory before you remove an entity (that includes on level changes, for example via on_ent_remove). Keep it simple, makes it easier to debug and less error prone.
Posted By: jumpman

Re: Ways to send variables/locations to entity shaders - 08/08/18 05:30

Txesmi, Superku, Im using both of your methods and it works so far! Thank you so much.

Just curious, didnt you allocate memory with:

float floatArray[4];

Will that be released automatically once the entity is removed?
Posted By: Superku

Re: Ways to send variables/locations to entity shaders - 08/08/18 08:34

No, not directly, that's just grabbing memory from the stack as with any other variable. For example writing "int i;" before a for(i ...) loop. That memory will be "lost" on function exit (but restored after when there is a "wait" instruction).
© 2024 lite-C Forums