Posted By: oliver2s
Slope Blendmap Generator - 12/11/13 19:43
This code generates a blendmap out of a given heightmap. The angles which defines a slope (between 0-90 degrees) can be adjusted via function parameter.
All scripts to make a terrain like in the screenshot above:
1. Combine a Perlin Noise Heightmap of 2/3 with a Voronoi Heightmap of 1/3
2. Use the Perturbation Filter over the combined heightmap.
3. Run the Hydralic Erosion Script over the heightmap.
4. Blur it a litte bit (had no script yet for this, made this in Photoshop)
Code:
BMAP* bmap_heightmap_to_normalmap(BMAP* bmap_hmap_,BMAP* bmap_nmap_,var factor_); //Make Blendmap from Heightmap on slopes /////////////////////////////// // bmap_hmap_ -> heightmap // bmap_blendmap_ -> blendmap which will be painted or NULL for creating new blendmap // color_ -> color which will be painted in blendmap on slopes // gradientMin_ -> angle of slopes where painting should begin (range 0-90) // gradientMax_ -> angle of slopes where painting should stop (range 0-90) /////////////////////////////// BMAP* bmap_heightmap_to_blendmap_slopes(BMAP* bmap_hmap_,BMAP* bmap_blmap_,COLOR* color_,var gradientMin_,var gradientMax_) { //clear up gradients var gradient_min_=gradientMin_; var gradient_max_=gradientMax_; if(gradient_max_<gradient_min_) { gradient_max_=gradientMin_; gradient_min_=gradientMax_; } gradient_min_=clamp(gradient_min_,0,90); gradient_max_=clamp(gradient_max_,0,90); if(gradient_min_==gradient_max_){ return NULL; } //store color COLOR c1_; c1_.red=color_.red; c1_.green=color_.green; c1_.blue=color_.blue; //get size var size_x_=bmap_width(bmap_hmap_); var size_y_=bmap_height(bmap_hmap_); //create tmp normalmap bmap BMAP* normalmap_=bmap_heightmap_to_normalmap(bmap_hmap_,NULL,1); //create temp bitmap for blendmap BMAP* blendmap_=bmap_createblack(size_x_,size_y_,24); //search slopes within the given range on normalmap int py; for(py=0;py<size_y_;py++) { int px; for(px=0;px<size_x_;px++) { //get normalmap pixel COLOR c_; var format=bmap_lock(normalmap_,0);var alpha_; var pixel=pixel_for_bmap(normalmap_, px, py); pixel_to_vec(c_,alpha_,format,pixel); bmap_unlock(normalmap_); //convert normalmap pixel to normal vector VECTOR n; n.x = 2.0*(c_.red-128); n.y = 2.0*(c_.green-128); n.z = 2.0*(c_.blue-128); //normalize to 0-1 vec_normalize(n,1); //get Euler angle var angle = 90-asinv(abs(n.z)); //if angle is between given angles, paint blendmap if(angle>=gradient_min_ && angle<=gradient_max_) { //paint given color to blendmap var format=bmap_lock(blendmap_,0); var pixel=pixel_for_vec(c1_,100,format); pixel_to_bmap(blendmap_, px, py, pixel); bmap_unlock(blendmap_); } } } //remove tmp normalmap bmap_purge(normalmap_); bmap_remove(normalmap_); //return new created blendmap if no target bitmap was passed to function if(bmap_blmap_==NULL){return blendmap_;} else { //otherwise copy created blendmap to target bitmap bmap_blit(bmap_blmap_,blendmap_,NULL,vector(bmap_width(bmap_blmap_),bmap_height(bmap_blmap_),0)); //delete temp bitmap bmap_purge(blendmap_); bmap_remove(blendmap_); //return return bmap_blmap_; } } BMAP* bmap_heightmap_to_normalmap(BMAP* bmap_hmap_,BMAP* bmap_nmap_,var factor_) { //get size var size_x_=bmap_width(bmap_hmap_); var size_y_=bmap_height(bmap_hmap_); BMAP* normalmap_=bmap_createblack(size_x_,size_y_,24); int py; for(py=0;py<size_y_;py++) { int px; for(px=0;px<size_x_;px++) { //get height of 3 neighbor pixels COLOR color_; var c1,c2,c3; var format=bmap_lock(bmap_hmap_,0);var alpha_; var pixel=pixel_for_bmap(bmap_hmap_, clamp(px-1,0,size_x_), clamp(py-1,0,size_y_)); pixel_to_vec(color_,alpha_,format,pixel); c1=color_.red; var pixel=pixel_for_bmap(bmap_hmap_, clamp(px+1,0,size_x_), clamp(py-1,0,size_y_)); pixel_to_vec(color_,alpha_,format,pixel); c2=color_.red; var pixel=pixel_for_bmap(bmap_hmap_, clamp(px-1,0,size_x_), clamp(py+1,0,size_y_)); pixel_to_vec(color_,alpha_,format,pixel); c3=color_.red; bmap_unlock(bmap_hmap_); //build temporary points that makes a triangle VECTOR v1,v2,p1,p2,p3; p1.x=0;p1.y=0;p1.z=c1*factor_; p2.x=32;p2.y=0;p2.z=c2*factor_; p3.x=0;p3.y=32;p3.z=c3*factor_; //get first vector for cross product (p2-p1) v1.x=p2.x-p1.x; v1.y=p2.y-p1.y; v1.z=p2.z-p1.z; //get second vector for cross product (p3-p1) v2.x=p3.x-p1.x; v2.y=p3.y-p1.y; v2.z=p3.z-p1.z; //calculate cross product of v1 and v2 VECTOR n; vec_cross(n,v1,v2); //normalize to color range 0-255 vec_normalize(n,255); //convert vector into normalmap color n.x=n.x/2 + 128; n.y=n.y/2 + 128; n.z=n.z/2 + 128; //copy color COLOR color1_; color1_.red=n.x; color1_.green=n.y; color1_.blue=n.z; //get height of another 3 neighbor pixels COLOR color_; var c1,c2,c3; var format=bmap_lock(bmap_hmap_,0);var alpha_; var pixel=pixel_for_bmap(bmap_hmap_, clamp(px+1,0,size_x_), clamp(py+1,0,size_y_)); pixel_to_vec(color_,alpha_,format,pixel); c1=color_.red; var pixel=pixel_for_bmap(bmap_hmap_, clamp(px-1,0,size_x_), clamp(py+1,0,size_y_)); pixel_to_vec(color_,alpha_,format,pixel); c2=color_.red; var pixel=pixel_for_bmap(bmap_hmap_, clamp(px+1,0,size_x_), clamp(py-1,0,size_y_)); pixel_to_vec(color_,alpha_,format,pixel); c3=color_.red; bmap_unlock(bmap_hmap_); //build temporary points that makes a triangle VECTOR v1,v2,p1,p2,p3; p1.x=32;p1.y=32;p1.z=c1*factor_; p2.x=0;p2.y=32;p2.z=c2*factor_; p3.x=32;p3.y=0;p3.z=c3*factor_; //get first vector for cross product (p2-p1) v1.x=p2.x-p1.x; v1.y=p2.y-p1.y; v1.z=p2.z-p1.z; //get second vector for cross product (p3-p1) v2.x=p3.x-p1.x; v2.y=p3.y-p1.y; v2.z=p3.z-p1.z; //calculate cross product of v1 and v2 VECTOR n; vec_cross(n,v1,v2); //normalize to color range 0-255 vec_normalize(n,255); //convert vector into normalmap color n.x=n.x/2 + 128; n.y=n.y/2 + 128; n.z=n.z/2 + 128; //copy color COLOR color2_; color2_.red=n.x; color2_.green=n.y; color2_.blue=n.z; COLOR color_; color_.red=(color1_.red+color2_.red)/2; color_.green=(color1_.green+color2_.green)/2; color_.blue=(color1_.blue+color2_.blue)/2; //add to pixels var format=bmap_lock(normalmap_,0); var pixel=pixel_for_vec(color_,100,format); pixel_to_bmap(normalmap_, px, py, pixel); bmap_unlock(normalmap_); } } //return new created Normalmap if no target bitmap was passed to function if(bmap_nmap_==NULL){return normalmap_;} else { //otherwise copy created Normalmap to target bitmap bmap_blit(bmap_nmap_,normalmap_,NULL,vector(bmap_width(bmap_nmap_),bmap_height(bmap_nmap_),0)); //delete temp bitmap bmap_purge(normalmap_); bmap_remove(normalmap_); //return return bmap_nmap_; } }
All scripts to make a terrain like in the screenshot above:
1. Combine a Perlin Noise Heightmap of 2/3 with a Voronoi Heightmap of 1/3
2. Use the Perturbation Filter over the combined heightmap.
3. Run the Hydralic Erosion Script over the heightmap.
4. Blur it a litte bit (had no script yet for this, made this in Photoshop)