Absolute Beginners guide to using shaders

Discuss the construction of maps and the tools to create maps for 3D games.
OneManClan
Posts: 247
Joined: Sat Feb 28, 2009 2:38 pm
Contact:

Absolute Beginners guide to using shaders

Post by OneManClan »

[Update July 2015: added extra commands to help w debugging in notes section]

[BIG FAT DISCLAIMER: I'm a beginner to this, so I *barely* know what I'm doing. I've checked with Spike and GB (thanks HEAPS guys!!), so if the following is wrong, it's not insanely wrong. I'll be constantly editing this page as new info comes in, or if I think of a clearer way to describe something, so anyone reading this please check back, and read the comments/corrections/clarifications (below) from those who know more than I]

INTRODUCTION
Hi all. Inspired by some [edit: the following link is now dead] tantalising screenshots of GBs upcoming Scout's Journey, I've delved into the world of shaders. All the stuff I rtfmed however was to do with the writing of shaders, but not the implementation, no 'step by step' guide to actually putting one in a map [EDIT: specifically a q1 map using a q1 map editor]], and now that I've (finally) got one working(!), here's the guide I wish I had, the guide for absolute beginners.

BACKGROUND INFO: WHAT'S A SHADER?
A shader is a "short text script that define the properties of a surface as it appears and functions in a game world (or compatible editing tool)". The definition comes from here, where you'll also find a terrific instruction manual, and here's more info on how to write your own. These links deal with the 'q3 shader language', which is what you'll be using in your Quake engine based game. Also useful to get your head around the concept (and possibilities) of shaders is this video of the amazing Andrew Price explaining Blenders compositor, which is kind of like a 'shader maker' with a GUI interface. The jargon is different, but concept/principle IIUC is essentially the same, and the 'nodes' concept let you see and control the (equivalent of) changing different 'lines of shader code', in real time. [UPDATE: Also, here's a FANTASTIC Introduction to OpenGL Shaders; though the actual coding examples (in the second half) are NOT compatible with the q3 shader language that FTE and DP use]

THE QUAKE SITUATION
Regarding Quake, shaders need engines which can read shader scripts, and run them on the surfaces to which they are assigned. The only engines that support this AFAIK are FTEQW and DP. Their shader code/implementation is not 100% interchangable/compatible, so I'll deal with FTE, which is the one I use. Re: map editors, some (like NetRadiant) allow you to assign shaders to brushes, but others (eg TrenchBroom) don't. So how do you implement shaders in a q1 map editor? Where do we begin? Here's what do to:
  • 1. Make a texture which will be the default 'dummy' texture, lets call it “foo.tga”. Like all Quake textures, this needs to have dimensions which are powers of 2, eg 16 x 16, 128 x 256, etc. The purpose of this texture is to identify the brush surface you want the shader to 'do its magic' on.

    2. Add “foo.tga” to the wad you're using for your map.

    3. In the map editor, assign “foo.tga” to the surface you want to 'run' the shader on (not sure if that's the correct way to put it). Let's call this surface the "TargetSurface".

    4. Compile the map

    5. Make a text file called 'foo.shader'
    Inside this file put the following code:

    Code: Select all

    foo
    {
    // this is where you put the foo shader code
    // any surface assigned the texture "foo" will receive the output of this code
    }
    
    6. Save 'foo.shader' in Quake\FTE\scripts
Now when the map runs, FTE will load all the textures (including 'foo.tga'), and then check the Quake\FTE\scripts folder, looking through all the *.shader files for any shader called 'foo', and (if found) will 'run the foo code' on the TargetSurface.

Clients which are NOT 'shader compatible' will display the actual “foo.tga” on the TargetSurface.

Notes:
1. Some editors (NetRadiant is one) can assign shaders on textures in the actual map editor, so you don't need the extra step of making the 'dummy texture'.

2. In the example above, the foo shader doesn't have to exist in it's own individual file ("foo.shader"). It can exist in any *.shader file in the Quake\FTE\scripts folder.

3. Some shaders modify existing textures rather than replace them, so foo.tga (in the example above) might need to be a good 'basis' on which to perform shader operations on. Otoh, shaders can contain links to the images they use as 'inputs', so foo.tga might just need to be something that looks 'acceptable' in the map editor, or to any player who isn't using a shader compatible client.

your corrections/comments welcome.

UPDATE: The FAQ [ July 2015]
Q: How can I tell if the current map is trying to run my shader? How can I get a list of all the textures being used?
A: Type 'mod_texturelist'. You should have an entry there which matches the name of your shader. [credit: Spike]

Q: I've written different versions of the foo shader, how do I know which one is being run?
A: Type 'r_showshader foo' at the client console, and it will show you the 'currently running' foo code [credit: Spike]

Q: I'm making multiple changes to shader code, how can I quickly see the effect of different values?
A: Typing 'vid_restart' reloads all textures and shaders
Last edited by OneManClan on Fri Sep 06, 2019 5:56 am, edited 22 times in total.
gnounc
Posts: 428
Joined: Mon Apr 06, 2009 6:26 am

Re: Absolute Beginners guide to using shaders

Post by gnounc »

Pretty good guide, I think that appears to cover it pretty well.
I know you linked some articles, but could you walk us through building a simple shader script?
You said you can link input textures, that would be useful in an example post too.
thx.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Absolute Beginners guide to using shaders

Post by Spike »

The syntax of Quake3 shaders are defined here:
http://www.heppler.com/shader/

DP supports only a single pass (and lightmap). While limited, what is supported is robust.
FTE supports multiple passes, but in doing so can get potentially confused when it comes to realtime lights (ie: map specifies only the diffuse map, blend modes are currently ignored with rtlights etc). 'surfaceparm nodlight' can be used to block rtlights on surfaces, which should remove the issue.

Both engines have their own extensions. I can't really speak for DP as I've not really cared to read up on its extensions, but I can try and explain some of the fun crazyness you can do with fte...

Here's fte's terrain shader. This is normally built in, but could be loaded from an external source if desired.

Code: Select all

terrainshader
{
 bemode rtlight
 {
  {
   map $diffuse
   blendfunc add
  }
  {
   map $upperoverlay
  }
  {
   map $loweroverlay
  }
  {
   map $fullbright
  }
  {
   map $lightmap
  }
  {
   map $shadowmap
  }
  {
   map $lightcubemap
  }
  program terrain#RTLIGHT
 }
 bemode depthdark
 {
  program depthonly
  {
   depthwrite
  }
 }
 bemode depthonly
 {
  program depthonly
  {
   depthwrite
   colormask
  }
 }
 {
  map $diffuse
 }
 {
  map $upperoverlay
 }
 {
  map $loweroverlay
 }
 {
  map $fullbright
 }
 {
  map $lightmap
 }
 program terrain
 if r_terraindebug
  program terraindebug
 endif
}
and here's the glsl associated with it:
http://sourceforge.net/p/fteqw/code/HEA ... rrain.glsl

Now, I should explain some of it...
bemode blocks (which will masively confuse DP) are actually separate shaders embedded within the parent shader. these embedded shaders are used for the different backend modes. depthonly is used for a few things, including shadows. depthdark is used as an optimisation when r_shadow_realtime_world_lightmaps (wow long cvar) is set to 0. while the rtlight backend mode is used when drawing rtlights (and should thus be additively blended).

when using glsl (via the program command, which could include embedded glsl if desired), the engine uses a different pathway and just passes the geometry to the glsl to deal with, skipping any cpu vertex processing. all passes are combined into a single glsled multitexture pass, with the map command from each pass setting the glsl's s_tX uniforms. the various bits that are not completely ignored by glsl is still used (read: blend modes) but the other passes contribute *only* their map commands (which could be videomap or whatever instead, of course).

the map command can name either an actual image name, or some special name that the engine evalutes as required.
$diffuse - the regular texture that would normally be used, ie: foo.tga
$upperoverlay - the foo_upper.tga image, for high-res player skins and stuff
$loweroverlay - the foo_lower.tga image, for high-res player skins and stuff
$fullbright - the foo_luma.tga image, that is normally added, ignoring the lighting
$lightmap - the lightmap image that the surface uses.
$shadowmap - when drawing using rtlight shadowmapping, this is the depth texture that is sampled from. only really valid for a bemode rtlight shader.
$lightcubemap - when drawing rtlights, this is the light's light projection cubemap. a filter type thing for the rtlight. only really valid for a bemode rtlight shader.
$currentrender - use the current scene as a texture input. This can be used to easily draw weird distortions and things. be careful with shader sort orders.
$reflection - use a reflection rendermap. only works on a planer surface.
$refraction - use a refraction rendermap. only works on a planer surface (refraction is kinda like from the current view angle, but cut off at the water plane)
$ripplemap - uses some weird rendermap containing only shaders with 'sort ripplemap'. can be slow on a gffx... make particles generate quads with ripples in them and distort your water surface based upon those ripples. fun stuff.
$sourcecolour - some source colour rendermap that's set somehow. used internally for a few things.
$sourcedepth - some source depth rendermap that's set somehow. used internally for a few things.

Note that in this example, the engine internally uses the diffuse, upper, lower, and fullbright textures for the ground. while the lightmap texture is actually used to tell the engine how to mix the 4 images instead of modulating colours. In this way, fte's terrain system supports painting up to 4 textures in each terrain section.

Right... That's that badly explained... now for the glsl.
GLSL comes in two parts.
The vertex program, and the fragment(read:pixel) program.
The vertex program essentually just reads the various vertex attributes and writes various transformation results into 'varying' values. It is the vertex program that actually does the projection stuff to transform a 3d modelspace point into the same coordinate system the viewport uses.
The hardware then clips the verticies to the screen and interpolates those 'varying' values linearly across the triangles that it was given, calling the fragment program once for each pixel drawn.
GLSL has a few different classes of variables:
uniforms. these are variables which are readonly to the glsl. the engine sets them according to whatever entity/etc is getting drawn.
attributes. these are the per-vertex attributes. they're readable only by the vertex program.
varying. these are the outputs of a vertex program (typically a copy of some attribute variable), and inputs to the fragment program, smoothly interpolated across the fragment/triangle.

To keep things portable, FTE avoids the use of legacy built-in stuff because that sort of thing doesn't work with gles2.
you should thus use ftetransform() as an alternative to ftransform() (yeah, I know, gimmicky name, but whatever). on desktop gl, this will often just map to ftransform anyway, but that's not the point.


here's a list of some of the various attributes that fte defines. figure out the types and meaning yourself!
v_position, v_colour, v_texcoord, v_lmcoord, v_normal, v_svector, v_tvector, v_bone, v_weight

here's a list of some of the various uniforms that fte defines.
m_model, m_view, m_modelview, m_projection, m_modelviewprojection, m_bones, m_invviewprojection, m_invmodelviewprojection, v_eyepos, w_fog, e_vblend, e_lmscale, e_origin, e_time, e_eyepos, e_colour, e_colourident, e_glowmod, e_uppercolour, e_lowercolour, e_light_dir, e_light_mul, e_light_ambient

the !!permu thing at the start is another fteism. Each glsl file/block can optionally define multiple permutations, which means that certain steps can be skipped to avoid unneeded work. The shader knows which permutation it is based on #defines that the engine sets up before compiling the glsl.
Note that any program with a # after the name states that the glsl used should be some other explicit custom permutation. #foo=3.0 can also be used to set This allows you to make your glsl a bit more customisable. In the terrain example, this is used to allow a single block of glsl to be used for both standard rendering and with rtlights. Note that rtlights have a few permutations of their own...
These are the built in permutations.
bump (glsl provides an alternative pathway for when this texture is available, to reduce texture samples, you can be lazy and assume its always there, then you can omit the permutation)
fullbright (glsl provides an alternative pathway for when this texture is available, to reduce texture samples)
upperlower (glsl provides an alternative pathway for when these textures are available, to reduce texture samples)
deluxe (glsl provides an alternative pathway for deluxemapping, so any costs don't affect stuff when its disabled)
skeletal (glsl supports gpu-based skeltal animation. #include "sys/skeletal.h" and use skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 s, out vec3 t) instead of ftetransform, which also gives the animated coord, normal, sdir and tdir values in modelspace)
fog (glsl supports #include "sys/fog.h" and use fog3/fog4/fog3additive/etc as a final part of its fragment program to add fog to the pixel)
frameblend (ftetransform+v_position are set up to blend between v_position1 and v_position2 instead)
lightstyled (v_lmcoord2, $lightmap2, etc, will be used by the glsl)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Absolute Beginners guide to using shaders

Post by Spike »

here's a boring wall shader:

Code: Select all

mycustomshader
{
 {
  map $lightmap
 }
 {
  map textures/mycustomshader.tga
  tcgen base
  blendfunc filter
 }
 {
  map textures/mycustomshader_luma.tga
  blendfunc add
  depthfunc equal
 }
}
With FTE, if you want to explicitly use the texture from within the bsp, you can just specify $diffuse and $fullbright instead of the two tgas specified. If you have no luma texture, you can just kill that part.
With DP, the third pass will technically be ignored, but the engine will add lumas based upon the diffuse texture path instead, or something, as well as load a normalmap too.
ajay
Posts: 559
Joined: Fri Oct 29, 2004 6:44 am
Location: Swindon, UK

Re: Absolute Beginners guide to using shaders

Post by ajay »

Hi
trying to get a Quake 3 grass shader working in Darkplaces, did a quick forum search and came up with this thread.

Anyway, the grass isn't working, before I do more digging and tweaking, a couple of basic questions:

1) Can darkplaces use .obj models (the shader uses one as the q3map_surfaceModel)
2) Do I have to compile the map with q3map2 to get this sort of thing working?

Many thanks
KillPixel
Posts: 3
Joined: Wed May 14, 2014 7:33 pm

Re: Absolute Beginners guide to using shaders

Post by KillPixel »

Nice post with nice links. Thanks, this will be handy.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Absolute Beginners guide to using shaders

Post by Spike »

ajay:
1)q3map2 handles the surfacemodel stuff and inserts it into the map as trisoup or some such, the engine doesn't need to support anything but the q3bsp format. this means that everything has the correct lighting instead of looking goofy.
2) the engine doesn't have anything to do with q3map_* settings. so yes, you need to use q3map2 in order to utilise those shader settings.
q1bsp does not support trisoup, so q1 tools won't do it. the engine can't/won't randomly do it as it expects the compiler to have done any of that stuff already (and yeah, screwy lighting or really long load times...).
ajay
Posts: 559
Joined: Fri Oct 29, 2004 6:44 am
Location: Swindon, UK

Re: Absolute Beginners guide to using shaders

Post by ajay »

Cheers Spike; so it won't work like the shader for water, which is a shame. Is there a grass shader that does work with quake tools, rather than q3?
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Absolute Beginners guide to using shaders

Post by Spike »

no. make a static entity instead.
ajay
Posts: 559
Joined: Fri Oct 29, 2004 6:44 am
Location: Swindon, UK

Re: Absolute Beginners guide to using shaders

Post by ajay »

I see, thanks. Therefore... can q1 maps be compiled with q3map2 "as is" or is there much work required? I guess some entities or brush functionality would be lost. Also, static entities; do you mean sprites? Sorry for questions, ajay.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Absolute Beginners guide to using shaders

Post by Spike »

q1bsp cannot sanely embed arbitrary geometry.
I believe quark can convert .map formats. LIghting algorithms will be significantly different (nicer, but less quakey). I imagine you'll need to faff around with water shaders, I'm not sure of any other differences.
By static entities, I mean the makestatic builtin, where the entity is thrown at the client and doesn't stay on the server etc. any model format.
Nahuel
Posts: 495
Joined: Wed Jan 12, 2011 8:42 pm
Location: mar del plata

Re: Absolute Beginners guide to using shaders

Post by Nahuel »

Hello Ajay I used quark to port q1 map to get compiled q3bsp:
The only thing you will loss is the lightstyles!

This is a little tut to do this in quark.
1- Open any q1 map, copy all the "worldspawn" stuff (entites and map structure)
2- Open a new map in quark with "quake 3" or "nexuiz (recomended)" selected game in "games"
3- delete the wolrdspawn of the default room of quake 3 (or nexuiz)
4- paste the q1 map wolrdspawn


This is all, to get a new q1 map- q3. But this map need a few changes
1- lightstyles will not work in q3bsp, and you will get weird errors with q3map2. so you need to delete all the lightstyles specifics in the light entities! But you can still use lightstyle (and switcheable) lights in a q3bsp in darkplaces. This is a very simple stuff, I wrote a tutorial for this in spanish, If you need it i will rewrite it here.


2- water and sky and clip and trigger shaders from quake 1 need to be rewriten to q3bsp (this is easy :) ), so you only need add this q1shaders to the q3 or nexuiz shaderlist.txt (you need to make a few change in traceline qc code to a correct work with clip, i copy this magictraceline from dpmod)

Code: Select all



textures/sky1
{
	surfaceparm sky
	surfaceparm noimpact
	surfaceparm nolightma
	nopicmip
}

textures/sky4
{
	surfaceparm sky
	surfaceparm noimpact
	surfaceparm nolightma
	nopicmip
}

textures/CLIP
{
	qer_trans 0.40
	surfaceparm nodraw
	surfaceparm nolightmap
	surfaceparm nonsolid
	surfaceparm trans
	surfaceparm nomarks
	surfaceparm noimpact
	surfaceparm playerclip
}
textures/TRIGGER
{
	qer_trans 0.50
	qer_nocarve
	surfaceparm nodraw
}

textures/*WATER0
{
	qer_editorimage textures/water/water0.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/water0.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1
}

textures/*WATER1
{
	qer_editorimage textures/water/water1.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/water1.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1
}

textures/*WATER2
{
	qer_editorimage textures/water/water2.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/water2.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1
}

textures/*04WATER1
{
	qer_editorimage textures/water/water1.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/water1.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1
}

textures/*04AWATER1
{
	qer_editorimage textures/water/water0.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/water0.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1
}

textures/*04MWAT2
{
	qer_editorimage textures/water/water0.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/water0.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1
}

textures/*04WATER2
{
	qer_editorimage textures/water/water1.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/water1.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1
}

textures/*04MWAT1
{
	qer_editorimage textures/water/water1.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/water1.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1
}

textures/*SLIME0
{
	qer_editorimage textures/water/slime0.tga
	qer_trans 20
	surfaceparm nomarks
	surfaceparm trans
	surfaceparm water
	surfaceparm nolightmap
	q3map_globaltexture
	{
		map textures/water/slime0.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.25 0.8  3 3  1 1 1  1 1 1  1
}

textures/*SLIME1
{
	qer_editorimage textures/liquids/slime1.jpg
	qer_trans 0.5
	surfaceparm noimpact
	surfaceparm trans
	surfaceparm nonsolid
	surfaceparm slime
	q3map_surfacelight 1750
	//deformVertexes wave 150.0 sin 2 5 0.25 0.1
	Q3map_TessSize 128
q3map_globaltexture
	{
		map textures/water/slime1.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1

}

textures/*SLIME2
{
	qer_editorimage textures/water/slime2.tga
	qer_editorimage textures/liquids/slime1.jpg
	qer_trans 0.5
	surfaceparm noimpact
	surfaceparm trans
	surfaceparm nonsolid
	surfaceparm slime
	q3map_surfacelight 1750
	//deformVertexes wave 150.0 sin 2 5 0.25 0.1
	Q3map_TessSize 128
q3map_globaltexture
	{
		map textures/water/slime1.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1

}

textures/*SLIME
{
	qer_editorimage textures/liquids/slime1.jpg
	qer_trans 0.5
	surfaceparm noimpact
	surfaceparm trans
	surfaceparm nonsolid
	surfaceparm slime
	q3map_surfacelight 1750
	//deformVertexes wave 150.0 sin 2 5 0.25 0.1
	Q3map_TessSize 128
q3map_globaltexture
	{
		map textures/water/slime.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}
	dp_water 0.1 0.8  3 3  1 1 1  1 1 1  1

}


textures/*TELEPORT
{
	qer_editorimage textures/#teleport.jpg
	dpoffsetmapping - 2
	dpglossintensitymod  3
	dpglossexponentmod  4


	{
		map textures/#teleport.jpg
				
	}

q3map_globaltexture
	{
		map textures/water/slime.tga
		tcMod scroll 0.25 0.25
		tcmod scale 0.35 0.18
		blendfunc blend
	}

}



I saw you are using some skybox soo this will not be a problem with the sky!
hi, I am nahuel, I love quake and qc.
ajay
Posts: 559
Joined: Fri Oct 29, 2004 6:44 am
Location: Swindon, UK

Re: Absolute Beginners guide to using shaders

Post by ajay »

Nahuel, that's really helpful. If you could post an english version of that tut, it would be great. I'm terrible (it's an age thing ;) ) in learning new stuff, once I get it, I'm fine, but anything outside of my current knowledge needs a lot of guidance ;) Thanks again.
Nahuel
Posts: 495
Joined: Wed Jan 12, 2011 8:42 pm
Location: mar del plata

Re: Absolute Beginners guide to using shaders

Post by Nahuel »

Well, this is off topic here so i will write a quick guide to use q1 maps to compile q3bsp´s with quark in this forum!
hi, I am nahuel, I love quake and qc.
ajay
Posts: 559
Joined: Fri Oct 29, 2004 6:44 am
Location: Swindon, UK

Re: Absolute Beginners guide to using shaders

Post by ajay »

That's excellent, thank you very much
Post Reply