Jump to content


Photo

Shader Extension 1.4


  • Please log in to reply
84 replies to this topic

#1 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 12 December 2010 - 06:47 PM

>>> Download <<<
Latest version: 1.4
Last updated: 22/Dec/2010

Download includes GEX, DLL files and source code. You only need the GEX.


Currently does not work with GM 8.1 onward.


Changelog
1.4: Fixed d3d_vs_create(), it was ignoring constants set by the 'def' instruction.
1.4: Changed VS configs so they work like the others. No overwriting without explicit definition.

1.3: Added z-bias control. Prevents z-fighting between coplanar polygons; useful for shadows and decals.
1.3: Added extended primitive functions which can draw up to 8192 vertices at once with position, normal, colour, specular, eight textures and eight sets of texture coordinates.
1.3: Added vertex shader 1.1 support and related functions. Due to GM's nefarious machinations, their use is limited to the the extended primitive functions.
1.3: Added helper functions which directly set shader constants to GM-format colours.
1.3: Changed configs: PS/VS/tex configs are now independent.
1.3: Changed d3d_set_tex_all: now sets stage 0 too. The extended primitive functions use it.
1.3: Demo has been updated with a water post-processing effect. Press P.

1.2: Added d3d_dev_get_ps_version, checks pixel shader support.
1.2: Added d3d_set_tex_border, sets colour and alpha for tex_wrap_border mode.
1.2: d3d_set_tex* functions now accept -1 as the tex parameter. This unbinds the texture from the stage making it safe to delete the associated resource in GM.
1.2: Fixed the extension's fillmode_ constants. They were named incorrectly.
1.2: Fixed d3d_set_tex_all in the DLL version. It was defined with the wrong number of arguments.
1.2: Fixed d3d_set_fog_color setting the wrong colours. D3D's colour format is RGB, not BGR.

1.1: First release.



ABOUT
Pixels shaders are awesome: powerful, fast and compatible. Now you can use them directly in GM!

But that's not all. You also get:

  • Alpha/Z testing
    Prevent pixels from being drawn using a customisable comparison. Alpha testing is often used in commercial games when drawing leaves and fences.
  • Configurable exponential fog
    More realistic fog for outdoor scenes.
  • Point primitive scaling and texturing
    Control the size of points and draw them with any texture applied.
  • Write masking
    Control red, green, blue, alpha and depth writing individually.
  • Multitexturing
    Pixel shaders allow you to draw up to six textures at once. Good for detail textures and more.
  • Wireframe and point rendering
    Handy for testing. Point rendering obeys the point primitive settings.
  • Z-bias
    Prevent z-fighting between geometry with the same coordinates. You could overlay wireframes on existing geometry without flickering, for example.
  • Automatic normal-vector normalisation
    Fixes lighting problems when scaling models.
  • Informational functions
    Get the max point and texture sizes, GPU name, shader support, free texture memory, etc. No more guessing.
  • Extended primitives
    Draw primitives with up to 8192 vertices, each with position, normal, diffuse and specular colour/alpha and up to eight textures with eight sets of texture coordinates.
  • Vertex shaders
    Manipulate extended primitives with per-vertex calculations, much like a pixel shader.





DEMO
Here's a demo I created. It demonstrates the shader functionality and is fairly well commented. Includes commented shader assembly.
Posted Image
Download EXE
Download GMK





HOW TO USE
All functions work both in 2D and 3D mode where applicable.
Functions evaluate true on success, or false on failure. -1 specifically signifies an input error.




Initialisation
scr_shader_init()
DLL only. The extension does this for you automatically.



Information
d3d_dev_get_name()
GPU name.

d3d_dev_get_point_max_size()
Maximum point primitive size.

d3d_dev_get_ps_version()
Max supported pixel shader version. 10 - 14. If < 10, the GPU doesn't support pixel shaders.

d3d_dev_get_tex_max_width()
d3d_dev_get_tex_max_height()
Maximum texture size. Applies to all graphical resources.

d3d_dev_get_tex_max_stages()
Maximum simultaneous textures. Limits number of textures you can use at once. Usually 8 even on integrated GPUs.

d3d_dev_get_tex_mem()
Free texture memory in bytes. Approximate.



Pixel Shaders
d3d_ps_create( "assembly" )
Compile pixel shader from assembly source. Returns index for use in other shader functions.

d3d_ps_destroy( shader )
Free memory used by a shader, destroying it.

d3d_set_ps( shader )
Set current pixel shader or -1 for none. Shaders work like blend modes; one at a time, on or off. Shading is done before fog drawing and alpha testing.

d3d_set_ps_const( constant, r, g, b, a )
Set pixel shader constant register. There are 8 registers indexed 0-7 each containing 4 values between -1 and 1. Equivalent to using "def" in shader assembly.

d3d_set_ps_const_col( constant, col, alpha )
Set a constant to a GM-format colour. Handy shortcut.

d3d_set_ps_conf( conf )
Set PS constants from a predefined configuration. Unset values do not override current ones. Much faster than specifying settings individually.



Vertex Shaders
d3d_vs_create( "assembly" )
Compile vertex shader from assembly source. Returns index for use in other functions. The input (vn) registers are set up as follows:
    Reg     Data             Format
    
    v0:     Position         XYZ
    v3:     Normal           XYZ
    v5:     Diffuse colour   RGBA
    v6:     Specular colour  RGBA
    v7-v14: Texture coords   XY

d3d_vs_destroy( shader )
Free memory used by a shader, destroying it.

d3d_set_vs( shader )
Set current vertex shader or -1 for none. GM's functions are not affected. For the extended primitive functions, these completely replace transform, lighting, colouring and texturing.

d3d_set_vs_const( constant, x, y, z, w )
Set VS constant register. There are 96 4-component registers available.

d3d_set_vs_const_col( constant, col, alpha )
Set constant to GM-format colour.

d3d_set_vs_const_matrix( constant )
Sets four constants as the transposed world*view*projection matrix. You can then use m4x4 oPos,v0,cn in the shader to transform the vertices in keeping with GM's normal behaviour. If you use the d3d_transform functions make sure you call this after them, otherwise the shader transform will be wrong. Ex: 0 would set c0,c1,c2,c3; 4 would set c4,c5,c6,c7.

d3d_set_vs_conf( conf )
Set VS constant registers from a predefined configuration. Only the defined settings are changed.



Textures
d3d_set_tex( stage, tex )
Set texture for this texture stage or -1 for none. Max simultaneous textures determines how many are available. GM overrides stage 0 whenever it draws something.

d3d_set_tex_all( tex )
Set texture for all texture stages. -1 unsets.

d3d_set_tex_int( stage, mode )
Set texture stage interpolation mode. Stage 0 is also controlled by texture_set_interpolation in GM. Use tex_int_ constant. Defaults to tex_int_nearest.
Modes:
tex_int_nearest: No filter. Pixelated.
tex_int_bilinear: Bilinear filter. Smooth.
tex_int_anisotropic: Angle-dependent filter. Currently useless, but will be properly supported in version 1.5.

d3d_set_tex_wrap( stage, xmode, ymode )
Set texture stage wrapping mode. Use tex_wrap_ constant. Works the same as texture_set_repeat(), except there are more options and independent X/Y controls.
Modes:
tex_wrap_normal: Repeats texture.
tex_wrap_mirror: Repeats texture, flipping at repeat boundaries.
tex_wrap_mirroronce: Mirrors once and clamps afterward.
tex_wrap_border: Solid colour/alpha is used if outside 0-1.
tex_wrap_clamp: No wrapping. Edge colour is used if outside 0-1.

d3d_set_tex_border( stage, col, alpha )
Set colour for tex_wrap_border.

d3d_set_tex_conf( conf )
Set texture stages from a predefined configuration. Only stages with settings defined in the conf are changed.



User-defined Configurations
These functions handle groups of settings. It's faster to set everything from a conf simultaneously than to set them all individually.

d3d_conf_ps_create()
Creates new pixel shader configuration and returns its index.

d3d_conf_ps_set( conf, constant, r, g, b, a )
Define PS constant state.

d3d_conf_vs_create()
Creates new vertex shader conf.

d3d_conf_vs_set( conf, constant, x, y, z, w )
Define VS constant state.

d3d_conf_tex_create()
Creates new texture stage conf.

d3d_conf_tex_set( conf, stage, tex, interp, xmode, ymode )
Define texture stage state.



Fog
d3d_set_fog_state( state )
Enable/disable fog without modifying fog settings.

d3d_set_fog_type( fog_type )
Set fog type. Use fog_type_ constants. GM normally uses fog_type_linear, but fog_type_exp is usually better.

d3d_set_fog_density( density )
Exponential fog density. 0-1.

d3d_set_fog_color( col )
d3d_set_fog_start( dist )
d3d_set_fog_end( dist )
Same as usual. You have to use these with exp/exp2 type fog or GM will override the type to linear.



Point Primitives and Sprites
d3d_set_point_size( size )
Set size of pr_pointlist primitives. Points always face the camera and are unaffected by standard rotation/scaling methods.

d3d_set_point_size_min( size )
d3d_set_point_size_max( size )
Set size clamp, useful for scaled points in 3D mode. Defaults are 1 and 64.

d3d_set_point_scale( state )
Enable/disable point scaling. This scales points based on their distance from the camera. You must configure the scaling with d3d_set_point_scale_ceof.

d3d_set_point_scale_coef( coef1, coef2, coef3 )
Configure point scaling formula. Defaults to (1,0,0).
Formula: size * sqrt(1/( ceof1 + (coef2*distancetocamera) + (coef3*sqr(distancetocamera)) ))

d3d_set_point_sprite( state )
Enable/disable texture mapping for point primitives.
NOTE: You must define a texture for the primitive with draw_primitive_begin_texture or similar. Texcoords are ignored. 0,0 -> 1,1 covers the entire point irrespective of your inputs.



Render Control
d3d_set_mask( r, g, b, a )
Enable/disable writing of each colour channel independently. Draw on a surface without affecting its alpha channel, for example.

d3d_set_zwrite( state )
Enable/disable depth buffer writing. Same as above except for depth.

d3d_set_zbias( bias )
Offsets drawing depth, allowing polygons with the same position to be drawn without z-fighting / flickering artifacts. Useful for shadows, decals, etc.
Objects drawn with higher values appear in front. Integer 0-16, 0 disables. 0 by default.

d3d_set_alphatest( value, mode )
Prevent drawing of pixels that fail the given alpha test. Value is 0-255. Use cmp_ constants for mode. Pass -1 as value to disable alpha testing. Any positive value enables. Because it causes less pixels to be drawn, alphatesting can improve performance.
For example, if you set (128,cmp_greaterequal) then only pixels with at least half opacity will be drawn.

d3d_set_ztest( mode )
Prevents drawing of pixels that don't meet the given depth criteria. Comparison is between current depth buffer and pixel depth. Use cmp_ constants. Defaults to cmp_lessequal.

d3d_set_fillmode( mode )
Render only points, wireframes or filled. Use fillmode_ constant. Defaults to fillmode_solid.

d3d_set_normal_auto( state )
Enable/disable automatic normal-vector normalisation. Should solve problems with model lighting when scaling.



Extended Primitives
d3d_primitive_begin_ext( primitive, textured )
Begin drawing an extended primitive. 8192 vertices max. Textured is true or false: you control which textures to use with the d3d_set_tex functions. To draw untextured, set to false and call d3d_set_tex_all(-1).

NOTE: When drawing with texcoords things work a little differently. Obviously I couldn't make a function with 22 arguments, so you have to specify coords separately for each vertex with d3d_vertex_ext_tex.

Drawing without texcoords works the same as usual:
d3d_primitive_begin_ext( pr_trianglestrip, false )
  d3d_vertex_ext()
  d3d_vertex_ext()
  d3d_vertex_ext()
d3d_primitive_end_ext()

But for textured ext primitives you must do this:
d3d_primitive_begin_ext( pr_trianglestrip, true )
  d3d_vertex_ext()
  d3d_vertex_ext_tex()     // Define up to 8 sets of texcoords, one per stage.
  d3d_vertex_ext_next()    // Finalises the current vertex.
  d3d_vertex_ext()
  d3d_vertex_ext_tex()
d3d_primitive_end_ext()    // Draw

Since these functions don't affect the texture stages themselves, you can still draw textured primitives without specifying coordinates regardless of whether "textured" is true or false. This is by design, since you might want to specify the coords in a vertex shader instead.


d3d_vertex_ext( x,y,z, nx,ny,nz, col,alpha, speccol,specalpha )
Position, normal, diffuse/specular colour and alpha. The specular has no effect unless you make use of it in a shader.

d3d_vertex_ext_tex( stage, xtex, ytex )
Set vertex texture coordinates. There are eight sets indexed 0-7, one for each texture stage.

d3d_vertex_ext_next()
When drawing with textures, call when finished with the current vertex to start defining the next one.

d3d_primitive_end_ext()
Draw the primitive.

draw_primitive_begin_ext( primitive, textured )
draw_vertex_ext( x,y, col,alpha, speccol,specalpha )
draw_vertex_ext_tex( stage, xtex, ytex )
draw_vertex_ext_next()
draw_primitive_end_ext()
Same thing in two dimensions.





ABOUT SHADERS
As you can see in my demo, shaders are extremely fast and flexible. You can perform tone mapping, colour control, refraction, blurring, and many other advanced techniques.

This extension supports shader model 1.4. This is relatively limited compared with newer versions but highly compatible, and still much more powerful than GM's default raster effect capabilities. Being nine years old has its advantages; pretty much every GPU on the entire planet supports it, even that crappy old Intel GMA950 in your netbook.



WRITING SHADERS
Shaders are written in assembly language. I'm not going to explain every little thing here, but I'll give you a general overview.

A shader has registers to hold data and instructions which perform various operations on them. Registers are like variables; instructions are like functions. Each register has four values; this can represent an RGBA colour, texture coordinates, or whatever you want.

A pixel shader executes once for every single pixel drawn while it's enabled.


Here's a simple shader. This gives the same output as normal drawing.
ps.1.4           // Declares shader version.  Mandatory for all shaders.
texld r0, t0     // Reads texture stage 0 at coords t0.
mul   r0, r0,v0  // Multiplies texture by drawing colour and stores result in r0.  Done.


This halves the alpha of the texture, ignoring image_blend/image_alpha:
ps.1.4
def   c0, 1,1,1,0.5  // Defines constant register.
texld r0, t0 
mul   r0, r0,c0      // Multiplies constant register by texture.


See the demo GMK for more complex and useful examples. Play around with them - you can't break anything, but you can learn a lot more than by reading the specs alone.


Registers
Temporary registers
r0, r1, r2, r3, r4, r5. Read/write.
Registers which can store the results of instructions. They have a guaranteed range of at least -8 to +8, usually way way larger on modern hardware.

r0 also acts as the output register. When the shader is finished r0 is drawn to the screen.


Constant registers
c0, c1, c2, c3, c4, c5, c6, c7. Read-only.
Holds user-defined values between -1 and 1. Constant registers can be set by the def instruction or from outside the shader with d3d_set_ps_const().


Texture address registers
t0, t1, t2, t3, t4, t5. Read-only.
Holds texture coordinates for the current pixel. Because of how GM works you'll only be using t0, which contains the current texture coordinates for whatever texture is being drawn. You can only use these registers with texture instructions. Note: You can use all of them with the extended primitive functions.


Colour registers
v0, v1. Read only.
Holds the vertex colours for this pixel. 0,0,0,1 is opaque black, 1,1,1,1 is opaque white. For example, when drawing a sprite v0 contains image_blend (RGB) and image_alpha (A). v1 contains the specular colour, only used with extended primitives.



Instructions

Arithmetic Instructions
The arguments for these can be temporary, constant or colour registers.

mov rn, src
The most basic instruction. Copies src to rn.

add rn, src1,src2
Add src1 and src2, write to rn.

sub rn, src1,src2
Subtract scr2 from src1.

mul rn, src1,src2
Multiply src1 by src2.

mad rn, src1,src2, src3
Multiplies src1*src2, then adds src3.

lrp rn, src1, src2,src3
Linear interpolation between src2 and src3 by amount src1. In other words: (src2 + ((src3-src2)*src1)).

cnd rn, src1, src2,src3
if (src1 > 0.5) {rn = src2} else {rn = src3}

cmp rn, src1, src2,src3
if (src1 >= 0) {rn = src2} else {rn = src3}

dp3 rn, src1,src2
Calculates dot product of the RGB components of the two inputs: (src1.r*src2.r)+(src1.g*src2.g)+(src1.b*src2.b). Since the dot is a single value, it writes the same result to all components of the destination register.

dp4 rn, src1,src2
Same as dp3, but calculates the dot of all four components.



Texture Instructions
texld rn, tn
Reads colour data from the associated texture stage at coordinates tn and places the result in rn.
Loading into r0 reads texture stage 0. r1 reads stage 1, r2 stage 2, etc.
r0,t0 is the current texture GM is drawing. Surface, sprite, background, whatever.
In phase 2 you can use rn registers as coordinates.

texcrd rn, tn
Like texld, except it copies the texture coordinates instead of reading the texture. You have to use a .rgb destination writemask with this instruction. (see below)

texkill tn
Prevents the pixel from being drawn if any of tn's RGB components are < 0.
In phase 2 you can use rn registers as coordinates.

texdepth r5
Writes to the zbuffer. I've never used this so you'll have to check the MSDN documentation. See below.


Instruction modifiers
You can modify the results of arithmetic instructions by appending modifiers to them.

_x2, _x4, _x8.
Multiply result by factor. Ex: add_x2 would add then multiply the result by 2.

_d2, _d4, _d8.
Divides result by factor.

_sat
Clamps result into the range 0-1. You can combine this with another modifier, ex: add_x2_sat.



Temporary register modifiers
You can modify the inputs to an arithmetic instruction if they come from a temporary register. These only affect the result, they don't change the register itself.

rn_bias
Subtracts 0.5 from input.

1-rn
Inverts input.

-rn
Negates input.

rn_x2
Multiplies input by 2.

rn_bx2
Subtracts 0.5 and multiplies by 2, in that order. This turns data in the range 0-1 into -1-1.



Destination/source masks
You can decide which channels of the destination register are written to or from. The syntax for this is: rn.rgba.
Any combination is allowed, but the masks must be given in order. Ex: rn.a, rn.rg, rn.ra, rn.gba, etc.
Using the rn.rgba mask gives the same result as not specifying any mask.


Instruction count and order
Instructions must be given in the following order:
Version
Constant
Texture
Arithmetic
Phase
Texture
Arithmetic

You can issue up to 6 texture instructions and 8 arithmetic instructions per phase. Constants are optional. Phase is optional as well; if you don't use it the default phase is 2. You can only access the vn registers and use rn as texture coordinates in phase 2. The phase instruction clears the alpha channel of all rn registers.

One other thing! If you use an instruction only on the RGB channels, you can simultaneously execute an instruction on the alpha channel by co-issuing it. The two then count as a single instruction, increasing performance. + signifies co-issue. Example:
 ps.1.4
 texld r0,     t0
 texld r1,     t0
 mov   r0.rgb, r1
+mov   r1.a,   r0


More Information
MSDN - instruction reference
MSDN - register reference
MSDN - modifier reference

GameDev.net - Instructions
GameDev.net - Modifiers



>>> Download <<<
Latest version: 1.4
Last updated: 22/Dec/2010

Edited by LSnK, 16 April 2011 - 10:21 PM.

  • 19

#2 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 12 December 2010 - 06:51 PM

WRITING SHADERS
I'll fill this in later. It's a little complicated.

Aww.

It's the most important part! Do you know of any good tutorials?
  • 4

#3 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 12 December 2010 - 06:59 PM

WRITING SHADERS
I'll fill this in later. It's a little complicated.

Aww.

It's the most important part! Do you know of any good tutorials?

I haven't been able to find much besides the not-particularly-helpful DirectX 8.1 SDK reference. However, I'll write up a tutorial myself in an hour or two. I would have already, except Firefox crashed and swallowed the entire bloody post.

For the moment, a good place to start is by fiddling around with the shaders in the example GMK. I commented them reasonably well.

Edit: Done. Added MSDN links too.

Edited by LSnK, 13 December 2010 - 01:51 AM.

  • 0

#4 Newly Discovered

Newly Discovered

    Harmonious Genius

  • GMC Member
  • 2475 posts
  • Version:GM8

Posted 12 December 2010 - 10:13 PM

awesome! do you know if this is possible to make working shadows?
  • 0

poof_sig.png


#5 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 12 December 2010 - 11:16 PM

awesome! do you know if this is possible to make working shadows?

You can do that with the Surface Fix extension. Look at model from light angle -> draw model in black to surface -> surface now contains shadow texture.

Should work just fine with this extension. You could smooth out the shadows with this, and multitexturing might be handy for applying the shadow to the terrain.
  • 0

#6 Rani_sputnik

Rani_sputnik

    GMC Member

  • GMC Member
  • 482 posts
  • Version:GM:Studio

Posted 13 December 2010 - 10:35 AM

This is a frieken sweet extension!!! It should be part of the key Game Maker frame-work. Mike did say he was looking at extending the capabilities of d3d and this is EXACTLY what he should do. You have integrated it so well with the existing dev language too. Congrats on a job very well done man
  • 0

My games - In DecemberBoy Goes to Space

Utilities & Extensions - FloxGM, Destroyable Terrain

Check out my website: ryanloader.me, or follow me: twitter.com/RaniSputnik


#7 Phantom107

Phantom107

    Graphics Enthusiast

  • GMC Member
  • 2774 posts
  • Version:GM:Studio

Posted 13 December 2010 - 10:58 AM

Very impressive functionality, although too bad it doesn't go any higher than PS 1.4.
  • 0

GMCSignature.png

 

The most advanced GM game yet. Check out the Titan Rush GMC topic here! Developed by Phantom Technology

Talented spriting artist, looking for work? PM me. I'm working on a small project and need assistance. :)


#8 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 13 December 2010 - 12:45 PM

Very impressive functionality, although too bad it doesn't go any higher than PS 1.4.

If only GM used DirectX 9... :(
  • 2

#9 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 14 December 2010 - 09:22 PM

Updated with some minor changes and fixes. See changelog in first post.
  • 0

#10 amd42

amd42

    GMC Member

  • GMC Member
  • 269 posts
  • Version:GM8

Posted 14 December 2010 - 10:58 PM

Awesome, I'm gonna go check this out as soon as I can figure out shader assembly (I know HLSL, so I'm guessing it shouldn't be too hard). Only thing I don't see though is vertex shader support - could you possibly add that? I'd like to try making some sort of per-pixel lighting thing but can't because otherwise there's no efficient way to get position and normal info in the pixel shader.
  • 0
"Computers in the future may weigh no more than 1.5 tons." - Popular Mechanics, 1949

#11 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 15 December 2010 - 07:41 PM

Only thing I don't see though is vertex shader support - could you possibly add that? I'd like to try making some sort of per-pixel lighting thing but can't because otherwise there's no efficient way to get position and normal info in the pixel shader.

I've been looking into that. The answer seems to be no: GM uses d3ddev->SetVertexShader() to set the FVF whenever you call a drawing function, overriding any shader you set.

Technically you could rewrite all the drawing functions to make it work. That's a bit beyond the scope of this extension though.

Edit: That said, maybe I will write extended primitive/mesh functions. I already verified that I can draw primitives directly from the DLL so it can't be too hard...

Edited by LSnK, 16 December 2010 - 08:54 PM.

  • 0

#12 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 20 December 2010 - 11:56 PM

Update: Version 1.3

Happy Christmas.


Changelog:

1.3: Added z-bias control. Prevents z-fighting between coplanar polygons; useful for shadows and decals.
1.3: Added extended primitive functions which can draw up to 8192 vertices at once with position, normal, colour, specular, eight textures and eight sets of texture coordinates.
1.3: Added vertex shader 1.1 support and related functions. Due to GM's nefarious machinations their use is limited to the the extended primitive functions.
1.3: Added helper functions which directly set shader constants to GM-format colours.
1.3: Changed configs: PS/VS/tex configs are now independent.
1.3: Changed d3d_set_tex_all: now sets stage 0 too. The extended primitive functions use it.
1.3: Demo has been updated with a water post-processing effect. Press P.


See first post and demo GMK for documentation and examples. I'll add mesh functions in the next version.

I added more shaders to the demo:
- Grayscale shader is now a controllable saturation shader.
- Blur shader now has a controllable variant with pentagonal sampling.
- Post-processing shader is now a water shader.
- Example vertex shader which does the standard transform.
- Alpha multiplication shader, should allow normal drawing on surfaces. (I didn't test it though)

The water looks damn nice in motion. Check it out! (Press P)
Posted Image

I might make a full-on water demo sometime, it's pretty simple to selectively vary the distortion, depth, colour, area, wave direction, etc on a per-pixel or per-vertex basis.
  • 4

#13 Potado

Potado

    GMC Member

  • New Member
  • 401 posts

Posted 22 December 2010 - 02:44 AM

That's great! I can't believe that I get such a high frame rate.

Though I'm quite confused on the basics of just setting up a basic shader and what the various functions do.

Edited by Potado, 22 December 2010 - 04:41 AM.

  • 1

#14 Schyler

Schyler

    Noskcirderf Derf

  • GMC Member
  • 2680 posts
  • Version:GM:Studio

Posted 22 December 2010 - 05:22 AM

Is it possible to find the XYZ position of a pixel in the world at shader time?
  • 0

#15 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 22 December 2010 - 08:26 PM

Is it possible to find the XYZ position of a pixel in the world at shader time?

Don't think so. What are you trying to do?
  • 0

#16 OpticalLiam

OpticalLiam

    GMC Member

  • New Member
  • 782 posts

Posted 22 December 2010 - 08:35 PM

I've been waiting to see a shader implementation ever since GMAPI was released. Great job!
  • 0

#17 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 22 December 2010 - 10:24 PM

I've been waiting to see a shader implementation ever since GMAPI was released. Great job!

Thanks.


Update: Version 1.4

Fixed a couple of bugs. If you were having really frustrating issues with vertex shaders... my bad.

1.4: Fixed d3d_vs_create(), it was ignoring constants set by the 'def' instruction.
1.4: Changed VS configs so they work like the others. No overwriting without explicit definition.

Edited by LSnK, 22 December 2010 - 10:44 PM.

  • 0

#18 xygthop3

xygthop3

    You may know me from such forums as "Shaders"

  • GMC Member
  • 3367 posts
  • Version:GM:Studio

Posted 23 December 2010 - 02:37 AM

This is an awesome extension and I really like the fact you're keeping up with bug fixes and updates but I'm going to hold off messing with this until you're finished updating.

Great work and thanks for this.
  • 0

#19 Schyler

Schyler

    Noskcirderf Derf

  • GMC Member
  • 2680 posts
  • Version:GM:Studio

Posted 23 December 2010 - 02:52 AM

Is it possible to find the XYZ position of a pixel in the world at shader time?

Don't think so. What are you trying to do?

I was going to keep a texture 1/4 the size of the world then load it into the secondary texture buffer. Retrieving the X/Y components of the pixel being rendered, I'd multiply it by the color on the secondary texture which represents visible areas (white->black) allowing me to effectively create a shader Fog Of War for my 3D RTS.

The problem is I'm not all that sure that its possible to retrieve the X, Y position of the pixel being rendered in the world, which blows my whole plan out the roof. Ofcourse if I can get the fog working, I'd also do volumetric water rippling ;D
  • 0

#20 GearGOD

GearGOD

    Deus Verus

  • GMC Member
  • 2153 posts

Posted 23 December 2010 - 07:08 AM

Is it possible to find the XYZ position of a pixel in the world at shader time?

I've never worked with the fixed function pipeline but if the vertex shader at any point knows the world position of the vertex, you can pass it on to the pixel shader like so:

float4x4 World;
float4x4 View;
float4x4 Projection;

struct VertexToPixel
{
	float4 Position   	: POSITION;    
	float4 Color		: COLOR0;
	float2 TextureCoords: TEXCOORD0;
	float4 WorldPos		: TEXCOORD1;
};


VertexToPixel ColoredVS( float4 inPos : POSITION, float4 inColor: COLOR, float2 UV : TEXCOORD0)
{	
	VertexToPixel output = (VertexToPixel)0;
    
	float4 worldPosition = mul(inPos, World);
	output.WorldPos = worldPosition;
    
	float4 viewPosition = mul(worldPosition, View);
	output.Position = mul(viewPosition, Projection);


	output.Color = inColor;
	output.TextureCoords = UV;
    
	
	return output;    
}

float4 ColoredPS(VertexToPixel input) : COLOR0
{ 
	return float4(input.WorldPos.xyz,1);
}

This produces assembly that looks something like this:
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
            //
            // Parameters:
            //
            //   float4x4 Projection;
            //   float4x4 View;
            //   float4x4 World;
            //
            //
            // Registers:
            //
            //   Name         Reg   Size
            //   ------------ ----- ----
            //   World        c0       4
            //   View         c4       4
            //   Projection   c8       4
            //
            
                vs_1_1
                dcl_position v0  // inPos<0,1,2,3>
                dcl_color v1  // inColor<0,1,2,3>
                dcl_texcoord v2  // UV<0,1>
            

                dp4 r4.x, v0, c0  // worldPosition<0>
                dp4 r4.y, v0, c1  // worldPosition<1>
                dp4 r4.z, v0, c2  // worldPosition<2>
                dp4 r4.w, v0, c3  // worldPosition<3>
                mov r4.x, r4.x  // worldPosition<0>
                mov r4.y, r4.y  // worldPosition<1>
                mov r4.z, r4.z  // worldPosition<2>
                mov r4.w, r4.w  // worldPosition<3>
                mov r0, r4  // output<10,11,12,13>
                dp4 r3.x, r4, c4  // viewPosition<0>
                dp4 r3.y, r4, c5  // viewPosition<1>
                dp4 r3.z, r4, c6  // viewPosition<2>
                dp4 r3.w, r4, c7  // viewPosition<3>
                dp4 r2.x, r3, c8  // output<0>
                dp4 r2.y, r3, c9  // output<1>
                dp4 r2.z, r3, c10  // output<2>
                dp4 r2.w, r3, c11  // output<3>
            
            #line 25
                mov r1, v1  // output<4,5,6,7>
                mov r5.xy, v2  // output<8,9>
            
            #line 29
                mov oPos, r2  // ::ColoredVS<0,1,2,3>
                mov oD0, r1  // ::ColoredVS<4,5,6,7>
                mov oT1, r0  // ::ColoredVS<10,11,12,13>
                mov oT0.xy, r5  // ::ColoredVS<8,9>
            
            // approximately 23 instruction slots used




                ps_1_4
                def c0, 0, 0, 0, 1
                texcrd r0.xyz, t1
            
                mov r0.xyz, r0  // ::ColoredPS<0,1,2>
              + mov r0.w, c0.w  // ::ColoredPS<3>



There's also one more limitation: it'll only work with pixel shader version 1.4. Anything before that will clamp the texcoords into [0,1] range unless they're used only to sample a texture.
  • 0
Engineers are not programmers. Stop thinking that you can save a few bucks by writing code yourself instead of hiring a programmer. Your code sucks.

#21 LumiéreDuSoleil

LumiéreDuSoleil

    Long Live the Sun

  • New Member
  • 55 posts

Posted 26 December 2010 - 05:11 PM

A little bit of Blinn-Phong magic with a jpeg-y normal map. Needs PS.2/3 to make a real lighting engine though ... can has PS.3?

Posted Image

/*
c0  ambient color
c1  light color
c2  light vector
c3  halfway vector
*/

lightDiffuse = d3d_ps_create
("
    ps.1.4
    texld r0,     t0
    dp3   r0.rgb, r0_bx2,c2
    mul   r0.rgb, r0,c1
    add   r0.rgb, r0,c0
");

lightSpec = d3d_ps_create
("
    ps.1.4
    texld r0,     t0
    
    dp3   r0,     r0_bx2,c3
    mul   r0,     r0,r0
    mul   r0,     r0,r0
    mul   r0,     r0,r0
    mul   r0,     r0,c1
");

Now, about textures ... when I try to use a surface as t1, it only picks up the 0,0 pixel. Is that an effect of "Because of how GM works you'll only be using t0", an inability to use surfaces as textures, or a correctable bug?

At any rate, awesome work.
  • 0

#22 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 27 December 2010 - 08:10 PM

Nice one.

Now, about textures ... when I try to use a surface as t1, it only picks up the 0,0 pixel. Is that an effect of "Because of how GM works you'll only be using t0", an inability to use surfaces as textures, or a correctable bug?

Neither. The catch is that texld chooses the texture stage based on the destination register. r0 samples stage 0, r1 samples stage 1, and so on. The tn registers only hold the interpolated texcoords for the current pixel, they have no relation with any particular stage. T1 gives you 0,0 because that's the default value. GM has only defines one set of texture coordinates.

Example:
ps_whatever = d3d_ps_create
("
      ps.1.4
      texld  r0,     t0     // Samples stage 0 at coords t0
      texld  r1,     t0     // Samples stage 1 at coords t0
      mul    r0,     r1,r0
");

The reason I mentioned being stuck with t0 is because it poses some limitations. You might not want to use the same texcoords when sampling multiple textures. There's always texcrd and some arithmetic, but you might not have instructions to waste on that when doing complex effects. That's partly why I added the extended primitives.
  • 0

#23 GearGOD

GearGOD

    Deus Verus

  • GMC Member
  • 2153 posts

Posted 28 December 2010 - 02:15 AM

Needs PS.2/3 to make a real lighting engine though ... can has PS.3?

SM2 is part of the DX9 spec. You're stuck with 1.4 so long as GM is stuck with DX8.
  • 0
Engineers are not programmers. Stop thinking that you can save a few bucks by writing code yourself instead of hiring a programmer. Your code sucks.

#24 xygthop3

xygthop3

    You may know me from such forums as "Shaders"

  • GMC Member
  • 3367 posts
  • Version:GM:Studio

Posted 28 December 2010 - 10:52 PM

Messing around with this a bit, seems to be quite powerful.
After a few modifications to your preturb shader and use a DUDV map to get the right result (hightmap didn't look quite right) I have a simple stained glass effect.

Now to just translate it to 3D, possiable?

Posted Image

Uploaded with ImageShack.us
  • 0

#25 LumiéreDuSoleil

LumiéreDuSoleil

    Long Live the Sun

  • New Member
  • 55 posts

Posted 30 December 2010 - 03:09 AM

@LSnK: makes sense.

---------

Multi-textured procedural spaceship damage.

Posted Image
  • 0

#26 xygthop3

xygthop3

    You may know me from such forums as "Shaders"

  • GMC Member
  • 3367 posts
  • Version:GM:Studio

Posted 02 January 2011 - 08:45 AM

I could really use a bit of advise/help with using multiple textures in the vertex shader but only a single texture per vertex not multi tex on a single vertex, seems as tho I'm missing something with the texture stages that I just can't work out.

Note: If I only use a single texture stage the result is perfect.

The result im currentl getting:

Posted Image

Uploaded with ImageShack.us

Create
tex1=sprite_get_texture(spr_sprite_1,-1)
tex2=sprite_get_texture(spr_sprite_2,-1)

    test_tex = d3d_conf_tex_create();
   d3d_conf_tex_set( test_tex, 0, tex1, 1, 1,1 );

	test_tex_2 = d3d_conf_tex_create();
   d3d_conf_tex_set( test_tex_2, 1, tex2, 1, 1,1 );
	
	d3d_set_tex( 0, test_tex );
	
	d3d_set_tex( 1, test_tex_2);

Draw
  	d3d_set_vs( vs_test );
  	d3d_set_vs_const_matrix( 0 );
  	d3d_set_tex( 0, test_tex );
  	d3d_set_tex( 1, test_tex_2);  
  	
  
  	d3d_primitive_begin_ext( pr_trianglelist, true )
 
  	d3d_vertex_ext(0,0,0,  1,1,1,  c_white,1,  0,1 )
  	d3d_vertex_ext_tex(1,0,0)   
  	d3d_vertex_ext_next()   

  	d3d_vertex_ext( 128,0,0,	1,1,1, c_white,1, 0,1 )
  	d3d_vertex_ext_tex(1,1,0)  
   	d3d_vertex_ext_next()  

  	d3d_vertex_ext( 128,128,0,  1,1,1, c_white,1, 0,1 )
  	d3d_vertex_ext_tex(1,1,1)	.
  	d3d_vertex_ext_next()   
  	
  	d3d_vertex_ext( 0,0,0,  1,1,1, c_white,1, 0,1 )
  	d3d_vertex_ext_tex(0,0,0)   
  	d3d_vertex_ext_next()   

  	d3d_vertex_ext( 128,128,0,  1,1,1, c_white,1, 0,1 )
  	d3d_vertex_ext_tex(0,1,1)	
  	d3d_vertex_ext_next()   

  	d3d_vertex_ext( 0,128,0,	1,1,1, c_white,1, 0,1 )
  	d3d_vertex_ext_tex(0,0,1)	
  	d3d_vertex_ext_next()   



   		d3d_primitive_end_ext();  

   	
    	d3d_set_vs( -1 );

And I'm using the VS shader from your example:
vs_test = d3d_vs_create
("
  	vs.1.1
  	m4x4 oPos,  v0,c0  // Position, transformed by matrix in c0-c3
    	
  	mov  oD0,   v5 	// Diffuse colour.  v0 in PS
  	mov  oD1,   v6 	// Specular colour. v1 in PS
  	
  	mov  oT0,   v7 	// Tex coords.  t0-t5 in PS.  6-7 are unavailable in PS.
  	mov  oT1,   v8
  	mov  oT2,   v9
  	mov  oT3,   v10
  	mov  oT4,   v11
  	mov  oT5,   v12
  	mov  oT6,   v13
  	mov  oT7,   v14
");

Edited by xygthop3, 02 January 2011 - 09:13 AM.

  • 0

#27 brac37

brac37

    GMC Member

  • GMC Member
  • 808 posts
  • Version:GM7

Posted 02 January 2011 - 06:22 PM

As it seems possible to integrate shader assembly, would it be possible to integrate x86 assembly in gamemaker as well, thus with a handle returned by a script asm_create, to be called with a stack of up to 16 doubles which may be pointers to strings or arrays of doubles rather than numbers?
  • 0

#28 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 02 January 2011 - 06:28 PM

As it seems possible to integrate shader assembly, would it be possible to integrate x86 assembly in gamemaker as well, thus with a handle returned by a script asm_create, to be called with a stack of up to 16 doubles which may be pointers to strings or arrays of doubles rather than numbers?

This.
  • 0

#29 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 03 January 2011 - 03:20 AM

The reason it draws wrong:

tex1=sprite_get_texture(spr_sprite_1,-1)
tex2=sprite_get_texture(spr_sprite_2,-1)

    test_tex = d3d_conf_tex_create();
   d3d_conf_tex_set( test_tex, 0, tex1, 1, 1,1 );

        test_tex_2 = d3d_conf_tex_create();
   d3d_conf_tex_set( test_tex_2, 1, tex2, 1, 1,1 );
        
        d3d_set_tex( 0, test_tex );
        
        d3d_set_tex( 1, test_tex_2);

d3d_set_tex accepts textures only. To set a conf use d3d_set_tex_conf.

It only draws something by coincidence - the first GM texture and the first conf both have the same index, zero.
  • 0

#30 xygthop3

xygthop3

    You may know me from such forums as "Shaders"

  • GMC Member
  • 3367 posts
  • Version:GM:Studio

Posted 03 January 2011 - 03:53 AM

ok now I changes the creation code to this

test_tex = d3d_conf_tex_create();
test_tex_2 = d3d_conf_tex_create();

test_tex = d3d_set_tex_conf(1 ) 
test_tex_2 = d3d_set_tex_conf(2)

and now nothing gets drawn at all, please help I would really like to understand how this works.

Thanks

Edited by xygthop3, 03 January 2011 - 03:55 AM.

  • 0

#31 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 03 January 2011 - 07:53 PM

ok now I changes the creation code to this

test_tex = d3d_conf_tex_create();
test_tex_2 = d3d_conf_tex_create();

test_tex = d3d_set_tex_conf(1 ) 
test_tex_2 = d3d_set_tex_conf(2)

and now nothing gets drawn at all, please help I would really like to understand how this works.

Thanks

That code makes no sense. Just ignore the conf functions for now. They're only for convenience/performance, it's not necessary to use them at all.

Do it directly like this:
tex1 = sprite_get_texture( spr_sprite_1, 0 );
tex2 = sprite_get_texture( spr_sprite_2, 0 );

d3d_set_tex( 0, tex1 );
d3d_set_tex( 1, tex2 );

Then draw the primitive. You also need to set a multitexturing pixel shader to draw the second texture. By default it will only draw the first texture.
  • 0

#32 Maxinston

Maxinston

    Epic Phail

  • GMC Member
  • 1248 posts
  • Version:Unknown

Posted 18 January 2011 - 07:21 AM

There doesn't seem to be a license included, are we allowed to use this for commercial games?
  • 0
<div align='center'><img src="http://img33.imagesh...igpic88821.jpg" border="0" class="linked-sig-image" />
A designer knows that he achieved perfection not when there is nothing left to add but when there is nothing left to take away.</div>

#33 GamerXP

GamerXP

    GMC Member?

  • GMC Member
  • 443 posts
  • Version:GM:Studio

Posted 18 January 2011 - 12:45 PM

Really cool. It works fast and easy to use. With this I can boost performance of my game a lot.

Is there normal maps for shader version 1.4?


  • 0

#34 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 18 January 2011 - 05:28 PM

There doesn't seem to be a license included, are we allowed to use this for commercial games?

Yes. You don't have to credit me either.

Is there normal maps for shader version 1.4?

LumireDuSoleil posted an example using one at the top of this page.
  • 0

#35 GamerXP

GamerXP

    GMC Member?

  • GMC Member
  • 443 posts
  • Version:GM:Studio

Posted 21 January 2011 - 12:45 PM

If there a way to apply shader to some area on the screen, using sprites with transparency as mask?
  • 0

#36 HaRRiKiRi

HaRRiKiRi

    GMC Member

  • GMC Member
  • 1364 posts

Posted 21 January 2011 - 08:05 PM

If there a way to apply shader to some area on the screen, using sprites with transparency as mask?

I think you just have to use surfaces. Render the screen to the surface and draw the surface_part with the shader.
  • 0

#37 GamerXP

GamerXP

    GMC Member?

  • GMC Member
  • 443 posts
  • Version:GM:Studio

Posted 21 January 2011 - 10:38 PM

Well, I used it before stared using shaders, but it works pretty slow. I thought maybe there is a way to make it faster with shaders or something like this
  • 0

#38 Captain Mangoes

Captain Mangoes

    GMC Member

  • GMC Member
  • 117 posts

Posted 22 January 2011 - 01:18 AM

Wow, I'm still reeling from this. Maybe in another hour I'll stop seeing code.

Great work!
  • 0

#39 HaRRiKiRi

HaRRiKiRi

    GMC Member

  • GMC Member
  • 1364 posts

Posted 23 January 2011 - 03:51 PM

Well, I used it before stared using shaders, but it works pretty slow. I thought maybe there is a way to make it faster with shaders or something like this

You used surfaces before to achieve some effect? That is not what I meant. To apply shader you need to have a texture. To apply shader to the screen you need to have the texture of the screen and that is where surfaces comes in. Check out the example at the first post, it has a full screen effect that is done this way. Now if you draw only parts of the surface then you can have partial screen effects (that's what you want I guess).
  • 0

#40 GamerXP

GamerXP

    GMC Member?

  • GMC Member
  • 443 posts
  • Version:GM:Studio

Posted 23 January 2011 - 05:13 PM

Well, that's how it worked before I used shaders. It makes clear transparent surface, then draw on it masks of areas I want to be grayscale and then draw screen's surface in special blend mode with shaders turned on, then draws surface I got.
I thought, maybe with shaders I can somehow make this durning draw events, not after I already rendered the screen and drew it - this way it may be much faster and I probably can make some objects stay colored (looks like it's impossible to make it the way I mentioned before without redrawing the scene once more)
  • 0

#41 jack1993jack

jack1993jack

    GMC Member

  • New Member
  • 231 posts

Posted 26 January 2011 - 03:02 AM

Awesome! Looks very nice ^_^
  • 0
Testing can be used to show the presence of bugs, but never to show their absence

#42 thatshelby

thatshelby

    GMC Member

  • GMC Member
  • 3823 posts
  • Version:GM8

Posted 10 March 2011 - 05:03 PM

Hey, nice work here. :D

I'd like to see an extended example, with this kinda stuff that you mention in the first post (Exponential fog, ztesting).
  • 0

#43 Nehacoo

Nehacoo

    GMC Member

  • New Member
  • 180 posts
  • Version:GM8.1

Posted 10 March 2011 - 05:12 PM

Hi, this extension is already great (although I'm mostly using it for the secondary features such as the exponential fog. How I've longed for exp fog in GM! :D), but this is particularly interesting to me:

tex_int_anisotropic: Angle-dependent filter. Currently useless, but will be properly supported in version 1.5.

Does this mean the next version will add mipmaps? Because that's pretty much my main issue with GM3D.
  • 0

#44 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 10 March 2011 - 07:55 PM

Hi, this extension is already great (although I'm mostly using it for the secondary features such as the exponential fog. How I've longed for exp fog in GM! :D), but this is particularly interesting to me:

tex_int_anisotropic: Angle-dependent filter. Currently useless, but will be properly supported in version 1.5.

Does this mean the next version will add mipmaps? Because that's pretty much my main issue with GM3D.

Yeah, that's the plan. Texture compression as well.

I have it working in a crappy experimental way but I didn't have time to properly integrate it yet.

By the way, I was actually wrong to say "useless" there because it does reduce jaggies even when mipmapping is off. It's just not as noticable an improvement and takes a collosal amount of memory bandwidth.
  • 1

#45 SebbeK

SebbeK

    GMC Member

  • New Member
  • 50 posts

Posted 01 April 2011 - 04:28 PM

What if i would like to make the whole screen grayscale, and nothing more. How would i do it? I've been messing around with the ctrl_postprocess for a while but i don't really get a hold of it...
  • 0

#46 GamerXP

GamerXP

    GMC Member?

  • GMC Member
  • 443 posts
  • Version:GM:Studio

Posted 02 April 2011 - 10:47 AM

Its really easy - you need only to use shader activator (d3d_set_ps( shader )), that work the same as blend modes. Place it in the step event so it will work for entire screen
  • 0

#47 SebbeK

SebbeK

    GMC Member

  • New Member
  • 50 posts

Posted 02 April 2011 - 12:27 PM

That is just awesome... Thanks alot! This was really needed for gamemaker
  • 0

#48 JakeX

JakeX

    GMC Member

  • New Member
  • 548 posts

Posted 05 April 2011 - 10:01 PM

Now if only I was any good at writing shaders.
(Something less archaic than model 1.4 would be nice too, but that's not your fault.)

Also, trying to define texture configurations in the first step of the game was causing the wonderful Unknown Error, but only when I ran the demo from a GMK. Strange.
  • 0

Posted Image


#49 Binsk

Binsk

    -Insane Kid-

  • GMC Member
  • 3111 posts
  • Version:GM:Studio

Posted 07 April 2011 - 04:11 AM

Looks beautiful and my brain is already exploding with ideas. However I haven't a clue how to write shaders, even after reading what you wrote. (Still confusing as heck... takes me a while to learn these things. :P )
How did you learn to write them? I have searched google multiple times for ways to learn how to write them with very little to no luck. Any help on the issue would be appreciated. Thanks, if you are willing to help. :)

P.S., Sorry, didn't read through the whole topic, so if you have already given an answer to something like this feel free to yell at me. :D
  • 1

NEWS FLASH! You can't get to heaven by your works. No chance. Hopeless. Give up now. No amount of works will get you anywhere, in fact all your efforts have been botched years ago because you already missed perfection the first time you lied, stole, or performed any of those other lovelies.

 

That said, do you want to go to heaven? Not the hellish picture given by cartoons. You know, the nightmarish one where you are renting a cloud and harp? I mean, holy crap, where did that come from? I am talking about a bonafide city, people, designed by God no less. Heck, read John's Revelation 21 if you want details. Getting to heaven is extremely simple, actually, the how and why is spelled out in Paul's letter to the Romans, summarized in Romans 10:9,10. God lived a perfect life and died in your place, covering every one of your mistakes and failures past and future. All you have to do is believe that He did what he said He did and accept the gift. Bam, you're saved. Done deal. Complicated, no? Questions? PM me.


#50 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 07 April 2011 - 07:21 PM

There's very little info about them on the Internet because very few people use shader assembly anymore.

I learned by experimenting with a shader editor, essentially a text field with a shader preview window. You could load textures, set constants and get real-time feedback. Tried out various things and got the hang of it after a while.

I can't find the one I used to use, 'ATI Shader Lab'. The DirectX SDK comes with 'MFC Pixel Shader' but it's pretty crap as a learning tool, you can't define constants or textures.


It's actually not very difficult to make a good one, especially with the WinAPI extensions for text editing. But I don't have time right now.
  • 0