Jump to content


Photo

Bump mapping


  • Please log in to reply
41 replies to this topic

#1 slayer 64

slayer 64

    GMC Member

  • GMC Member
  • 3274 posts
  • Version:GM8.1

Posted 28 October 2010 - 11:34 PM

- made in game maker 8 pro
- uses surface fix extension package

version 1
Normal mapping using grids and surface fix. load a heightmap image. get it's color values. calculate the normal vector for each point in the heightmap. take the dot product of each normal vector in the normal map and the light direction vector using ds_grid_multiply and ds_grid_add_region. create light and dark pixels and draw them over a texture using surface fix. use a multiply blend mode when drawing the pixels over the texture: draw_set_blend_mode_ext(bm_dest_color,bm_zero).

normal mapping version 2
i used a colorized model instead of ds grids. much faster than looping and drawing each pixel.

bump mapping version 3
i draw a model to a surface using lighting. i use surface textures all over the place for floor and walls. there's 1 floor and 4 walls. 5 different faces. 5 heightmaps need to be drawn to get the bump mapping effect for each face. i define each face using 3 vectors. i use the 3 vectors to convert the light direction vector into a faces space. i draw a model to a surface using the calculated light direction vector. i draw the surface to the walls and floor. everything is wrapped up in some scripts for easy use! =)

Bump Mapping Host-A

bump mapping version 3
Posted Image

normal mapping version 1
Posted Image

Edited by slayer 64, 02 November 2010 - 01:00 AM.

  • 3

#2 link3000

link3000

    Link3000

  • GMC Member
  • 1129 posts
  • Version:GM8

Posted 29 October 2010 - 01:43 AM

Beautiful. Great work, Slayer64!
  • 0

#3 amd42

amd42

    GMC Member

  • GMC Member
  • 269 posts
  • Version:GM8

Posted 29 October 2010 - 02:25 AM

I see that you got it working. Good job!
  • 0

#4 slayer 64

slayer 64

    GMC Member

  • GMC Member
  • 3274 posts
  • Version:GM8.1

Posted 29 October 2010 - 02:33 AM

I see that you got it working. Good job!


thanks
and thanks Link3000 =)

but it's not fast enough for me :( it runs at 20 fps and i wanted to add more polygons.
this is the slowest point:
for(ay=0;ay<ds_grid_height(gridDot);ay+=1)
{
    for(ax=0;ax<ds_grid_width(gridDot);ax+=1)
    {
        draw_point_color(ax,ay,merge_color(c_black,c_white,-min(0,ds_grid_get(gridDot,ax,ay))))
    }
}
those dam draw_point_colors! making the normal mapping area smaller; like 32x32 is better, meh :/
of course, i am writing low level code in high level game maker :S
this was still a fun project and learning experience =)
  • 0

#5 amd42

amd42

    GMC Member

  • GMC Member
  • 269 posts
  • Version:GM8

Posted 29 October 2010 - 03:07 AM

I've found a way to quickly compute the dot product in hardware by using a special texture blending option, but you can't access it normally from GM. I'll work on an update.
  • 0

#6 Phantom107

Phantom107

    Engineer

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

Posted 29 October 2010 - 11:19 AM

Looks great for native GM, although it runs very slow on this laptop: 20 fps. Runs 40-42 fps on my desktop.

The following optimization increased fps from 20 to 23-24:

Replace this:

for(ay=0;ay<ds_grid_height(gridDot);ay+=1)
{
    for(ax=0;ax<ds_grid_width(gridDot);ax+=1)
    {
        draw_point_color(ax,ay,merge_color(c_black,c_white,-min(0,ds_grid_get(gridDot,ax,ay))))
    }
}
With this:

ay = -1;
repeat ds_grid_height(gridDot)
begin
    ay += 1;
    ax = -1;
    repeat ds_grid_width(gridDot)
    begin
        ax += 1;
        
        draw_point_color(ax,ay,merge_color(c_black,c_white,-min(0,ds_grid_get(gridDot,ax,ay))))
    end;
end;
Luckily I have shader-based hardware powered normal mapping, hehehe.

Edited by Phantom107, 31 October 2010 - 01:23 PM.

  • 0

#7 Docopoper

Docopoper

    You are observant!

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

Posted 29 October 2010 - 10:10 PM

for(ay=0;ay<ds_grid_height(gridDot);ay+=1) { for(ax=0;ax<ds_grid_width(gridDot);ax+=1) {
draw_point_color
(ax,ay,merge_color(c_black,c_white, -min(0,ds_grid_get(gridDot,ax,ay)))) } }

--------------------------------------------

why don't you try writing all the points in a surface fix's saved surface format type file, and then just load that in as a surface.

Edited by Docopop.co.uk, 29 October 2010 - 10:11 PM.

  • 0

#8 Newly Discovered

Newly Discovered

    Harmonious Genius

  • New Member
  • 2467 posts
  • Version:GM8

Posted 31 October 2010 - 04:31 AM

Great example! I sure hope to see you put up some walls.
Mine ran at 26-27 fps and it looked beautiful.
  • 0

#9 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 31 October 2010 - 06:19 PM

Very nice effect, but too slow for realtime - I was getting {27~ fps}. Anyways, a further optimization that doubles my framerate to {51~ fps}.

ay = -1;
repeat ds_grid_height(gridDot)
begin
draw_primitive_begin(pr_pointlist);
    ay += 1;
    ax = -1;
    repeat ds_grid_width(gridDot)
    begin
        ax += 1;
        draw_vertex_color(ax,ay,merge_color(c_black,c_white,-min(0,ds_grid_get(gridDot,ax,ay))),1);
    end;
    draw_primitive_end();
end;


Then there's the option to DECREASE QUALITY to increase performance. Using this method I was getting {220~ fps}

Create rectangles 4x4 in size, and draw them with the color of the verticies of the color the pixels are. Then it will interpolate between them. I couldn't quite get it to draw correctly, which is why I'm not posting the code for it, but you could probably pull it off. If you get this working (with rectangles), I might transfer it to c++ in the form of a dll, to increase the framerates to a possibly acceptable fps.

Cheers
~~Brett14;

Edited by brett14, 31 October 2010 - 06:37 PM.

  • 0

#10 gm_user_tronic

gm_user_tronic

    GMC Member

  • GMC Member
  • 45 posts
  • Version:GM7

Posted 31 October 2010 - 08:31 PM

Looks pretty, can't wait for an update
  • 0

#11 slayer 64

slayer 64

    GMC Member

  • GMC Member
  • 3274 posts
  • Version:GM8.1

Posted 02 November 2010 - 01:08 AM

brett14, you caused me to make the code more efficient. now the example has enough speed for drawing walls and a floor at a minimum of 30 fps =)

my realization was to use models and heightmaps. i create a heightmap, use gm lighting, draw it to a surface and now we have bump mapping/normal mapping.

i feel like i've seen this technique somewhere on the gmc...

if someone was to use this in a game, they might want to make the heightmaps smaller. they are 64x64 right now. i think the example can still be more efficient. somebody take a look. =D
  • 0

#12 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 02 November 2010 - 01:13 AM

brett14, you caused me to make the code more efficient

I have a bad tendency to do that XD. I like to see code as optimized as possible.

i think the example can still be more efficient. somebody take a look

Will do. If I can find any more optimizations I'll post them. (Downloading right now) I will edit it after.

Cheers
~~Brett14;

Edited by brett14, 02 November 2010 - 01:22 AM.

  • 0

#13 Docopoper

Docopoper

    You are observant!

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

Posted 02 November 2010 - 10:19 PM

you should add point lights, and attempt triangles (should be easy enough)
  • 0

#14 michael pw

michael pw

    GMC Member

  • GMC Member
  • 1488 posts
  • Version:GM8.1

Posted 02 November 2010 - 10:32 PM

Damn Slayer how are you so good with Gm???? it boggles me?

anyway amazing effect, will probably use this at some point. :)
  • 0

#15 YellowAfterlife

YellowAfterlife

    GMC Member

  • Global Moderators
  • 3490 posts
  • Version:GM:Studio

Posted 03 November 2010 - 12:03 AM

To improve perfomance, you *could* try to make system array-based.
According to the following script-test, 2d array works not less than 25% faster than ds_grid (at last at my machine).
loops = 100
cycles = 10000
modval = 1024
mulval = 10000
io = "Output:"
//1d Array:
o = 0
for (j = 0; j < loops; j += 1)
{
t = date_current_time()
for (i = 0; i < cycles; i += 1) a1d[i mod modval] = i mod modval
v = date_current_time()
o += date_second_span(t,v)
}
o /= loops
io += "#1dArray: " + string(o * mulval)
//2d Array:
o = 0
for (j = 0; j < loops; j += 1)
{
t = date_current_time()
for (i = 0; i < cycles; i += 1) a1d[i mod modval,(i + 64) mod modval] = i mod modval
v = date_current_time()
o += date_second_span(t,v)
}
o /= loops
io += "#2dArray: " + string(o * mulval)
//DS Grid:
g = ds_grid_create(1024,1024)
o = 0
for (j = 0; j < loops; j += 1)
{
t = date_current_time()
for (i = 0; i < cycles; i += 1) ds_grid_set(g,i mod modval,(i + 64) mod modval,i mod modval)
v = date_current_time()
o += date_second_span(t,v)
}
o /= loops
ds_grid_destroy(g)
io += "#DS Grid: " + string(o * mulval)
show_message(io);
(code may be executed from anywhere, and may take a couple of seconds to execute under default configuration. Will show a messagebox with median execution time for 1d array, 2d array, and ds_grid)
  • 0

#16 slayer 64

slayer 64

    GMC Member

  • GMC Member
  • 3274 posts
  • Version:GM8.1

Posted 03 November 2010 - 01:06 AM

that code looks to be one-sided. the part that tests the 1d array has fewer calculations in it than the 2d and grid tests. it might be better to actually test the access time for 1d arrays, 2d arrays, and grids. and not include a bunch of extra math calculations to skew the results.
output="Output:"
loops=1000

//test 1d array
    time=current_time
    repeat loops a[0]=5
    output+="#1d array "+string(current_time-time)
    
//test 2d array
    time=current_time
    repeat loops a[0,0]=5
    output+="#2d array "+string(current_time-time)

//test grid
    time=current_time
    repeat loops ds_grid_set(grid,0,0,5)
    output+="#grid       "+string(current_time-time)

show_message(output)

the bump map example doesn't loop through 1000's of indexes. just 5. let's not get into what has better access time. if "loops" is set to 5, they all take 0 time to execute.
  • 0

#17 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 03 November 2010 - 05:57 AM

I have found that arrays are slightly faster than grids (long time ago). It isn't noticeable (like only a few percent) but there is some speed advantages.
HOWEVER - It takes ALOT longer to change values inside of an array on a mass scale (aka: multiply everything), so the system you're using at the moment is actually the fastest way (that I can think of) to do things.
  • 0

#18 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 03 November 2010 - 05:59 AM

I have found that arrays are slightly faster than grids (long time ago). It isn't noticeable (like only a few percent) but there is some speed advantages.
HOWEVER - It takes ALOT longer to change values inside of an array on a mass scale (aka: multiply everything, sort the array, etc.), so the system you're using at the moment is actually the fastest way (that I can think of) to do things.
  • 0

#19 Docopoper

Docopoper

    You are observant!

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

Posted 03 November 2010 - 06:23 PM

http://gmc.yoyogames...1

what about ds_bin - I don't know if it is actually faster though
  • 0

#20 slayer 64

slayer 64

    GMC Member

  • GMC Member
  • 3274 posts
  • Version:GM8.1

Posted 03 November 2010 - 11:49 PM

http://gmc.yoyogames...1

what about ds_bin - I don't know if it is actually faster though


yes arrays are faster; says so in the manual.
it doesn't matter. the bump mapping example doesn't lag from accessing lots of numbers in a ds grid. it lags if you draw models with lots of triangles in them. i was thinking of making more efficient models by removing triangles. but if someone wanted to make a bump map with lots of little details, you couldn't remove triangles. how can we achieve the same bump mapping effect with less cost? in gml :S
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users