GLuint GenSphereBumpmap() { GLuint id; glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); uchar img[3 * 64 * 64], *p = img; for (int y = 0; y < 64; y++) { for (int x = 0; x < 64; x++) { int sx = x - 32; int sy = y - 32; Vector3 n; if (sx*sx + sy*sy < 32*32) { const int sz = (int)sqrt(static_cast<float>(32 * 32 - sx*sx - sy*sy)); n = Vector3(sx, sy, sz); n.ANormalize(); } // compress it into a color *(p++) = (uchar)(255 * (n.x * 0.5f + 0.5f)); *(p++) = (uchar)(255 * (n.y * 0.5f + 0.5f)); *(p++) = (uchar)(255 * (n.z * 0.5f + 0.5f)); } } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, img); SaveImage("sphere_bm.jpg", 3, GL_UNSIGNED_BYTE, 64, 64, img); return id; }
void RenderDataManager::InitializeNode(TQuad* q) { assert(!q->renderData); QuadRenderData* rd = q->renderData = Allocate(); // Allocate vertex data space const size_t vertexSize = q->GetVertexSize(); if (static_cast<int>(vertexSize) != rd->vertexSize) { const size_t size = NUM_VERTICES * vertexSize; if (rd->vertexBuffer.GetSize() != size) { rd->vertexBuffer.Init(size); } rd->vertexSize = vertexSize; } // build the vertex buffer Vector3* v = (Vector3*)rd->vertexBuffer.LockData(); uint vda = q->textureSetup->vertexDataReq; // vertex data requirements const Heightmap* hm = roothm->GetLevel(q->depth); // get the right heightmap level for (int y = q->hmPos.y; y <= (q->hmPos.y + QUAD_W); y++) for (int x = q->hmPos.x; x <= (q->hmPos.x + QUAD_W); x++) { *(v++) = Vector3(x * hm->squareSize, hm->atSynced(x, y), y * hm->squareSize); Vector3 tangent, binormal; CalculateTangents(hm, x,y, tangent, binormal); Vector3 normal = binormal.cross(tangent); normal.ANormalize(); if (vda & VRT_Normal) *(v++) = normal; if (vda & VRT_TangentSpaceMatrix) { tangent.ANormalize(); binormal.ANormalize(); // orthonormal matrix, so inverse=transpose // Take the inverse of the tangent space -> world space transformation Vector3* tgs2ws = v; tgs2ws[0] = Vector3(tangent.x, binormal.x, normal.x); tgs2ws[1] = Vector3(tangent.y, binormal.y, normal.y); tgs2ws[2] = Vector3(tangent.z, binormal.z, normal.z); v += 3; } } rd->vertexBuffer.UnlockData(); rd->SetQuad(q); }
void Heightmap::GenerateNormals() { normalData = new uchar[3 * w * h]; uchar* cnorm = normalData; for (int y = 0; y < h;y++) for (int x = 0; x < w; x++) { Vector3 tangent, binormal; CalculateTangents(this, x, y, tangent, binormal); Vector3 normal = binormal.cross(tangent); normal.ANormalize(); *(cnorm++) = (uchar)((normal.x * 0.5f + 0.5f) * 255); *(cnorm++) = (uchar)((normal.y * 0.5f + 0.5f) * 255); *(cnorm++) = (uchar)((normal.z * 0.5f + 0.5f) * 255); } }
void Blendmap::Generate(Heightmap* rootHm, int lodLevel, float hmScale, float hmOffset) { const Heightmap* heightmap = rootHm->GetLevel(-lodLevel); // Allocate the blendmap image AlphaImage* bm = new AlphaImage; bm->Alloc(heightmap->w-1, heightmap->h-1); // texture dimensions have to be power-of-two Blendmap::GeneratorInfo* gi = generatorInfo; // Calculate blend factors using the function parameters and heightmap input: for (int y=0;y<bm->h;y++) { for (int x=0;x<bm->w;x++) { const float h = (heightmap->atSynced(x, y) - hmOffset) / hmScale; float factor=1.0f; if(h < gi->minHeight - gi->minHeightFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->minHeightFuzzy > 0.0f && h < gi->minHeight + gi->minHeightFuzzy) factor = (h - (gi->minHeight - gi->minHeightFuzzy)) / (2.0f * gi->minHeightFuzzy); if(h > gi->maxHeight + gi->maxHeightFuzzy) { bm->at (x,y) = 0.0f; continue; } else if (gi->maxHeightFuzzy > 0.0f && h > gi->maxHeight - gi->maxHeightFuzzy) factor *= ((gi->maxHeight + gi->maxHeightFuzzy) - h) / (2.0f * gi->maxHeightFuzzy); float norm_y = 0.0f; if (heightmap->normalData) { const uchar* cnorm = heightmap->GetNormal(x, y); norm_y = cnorm[1] / 255.0f * 2.0f - 1.0f; if (norm_y > 1.0f) norm_y = 1.0f; } else { Vector3 tangent, binormal; CalculateTangents(heightmap, x,y,tangent,binormal); Vector3 normal = tangent.cross(binormal); normal.ANormalize(); norm_y = normal.y; } // flatness=dotproduct of surface normal with up vector float slope = 1.0f - fabs(norm_y); if (slope < gi->minSlope - gi->minSlopeFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->minSlopeFuzzy > 0.0f && slope < gi->minSlope + gi->minSlopeFuzzy) factor *= (h - (gi->minSlope - gi->minSlopeFuzzy)) / ( 2.0f * gi->minSlopeFuzzy); if (slope > gi->maxSlope + gi->maxSlopeFuzzy) { bm->at(x,y) = 0.0f; continue; } else if (gi->maxSlopeFuzzy > 0.0f && slope > gi->maxSlope - gi->maxSlopeFuzzy) factor *= ((gi->maxSlope + gi->maxSlopeFuzzy) - h) / (2.0f * gi->maxSlopeFuzzy); factor *= gi->coverage; factor *= (rand() < gi->noise * RAND_MAX) ? 0.0f : 1.0f; bm->at(x,y) = factor; } } BlendmapFilter(bm); image = bm; }
Lightmap::Lightmap(Heightmap* orghm, int level, int shadowLevelDif, LightingInfo* li) { const spring_time startTicks = spring_gettime(); tilesize.x = orghm->w-1; tilesize.y = orghm->h-1; name = "lightmap"; const Heightmap* hm = NULL; int w; for(;;) { hm = orghm->GetLevel(-level); w = hm->w - 1; GLint maxw; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxw); if (w > maxw) level++; else break; } shadowLevelDif = 0; const Heightmap* shadowhm = orghm->GetLevel(-(level + shadowLevelDif)); int shadowScale= 1 << shadowLevelDif; int shadowW = shadowhm->w - 1; assert(w/shadowW == shadowScale); //float org2c = w/float(orghm->w-1); //float c2org = (float)(orghm->w-1)/w; float* centerhm = new float[w*w]; Vector3* shading = new Vector3[w*w]; for (int y=0;y<w;y++) for (int x=0;x<w;x++) { centerhm[y*w+x] =/* hm->scale * */ 0.25f * ( (int)hm->atSynced(x, y)+ (int)hm->atSynced(x + 1, y) + (int)hm->atSynced(x, y + 1) + (int)hm->atSynced(x + 1, y + 1) ); //+ hm->offset; shading[y*w + x] = li->ambient; } uchar* lightMap = new uchar[shadowW * shadowW]; for (std::vector<StaticLight>::const_iterator l = li->staticLights.begin(); l != li->staticLights.end(); ++l) { float lightx; float lighty; if (l->directional) { lightx = l->position.x; lighty = l->position.y; } else { lightx = (int)(l->position.x / shadowhm->squareSize); lighty = (int)(l->position.z / shadowhm->squareSize); } CalculateShadows(lightMap, shadowW, lightx, lighty, l->position.y, centerhm, w, shadowScale, l->directional); for (int y = 0; y < w; y++) { for (int x = 0; x < w; x++) { if (!lightMap[(y*shadowW + x) / shadowScale]) continue; Vector3 wp; if (l->directional) wp = l->position; else wp = l->position - Vector3((x + 0.5f) * hm->squareSize,centerhm[y*w + x], (y + 0.5f) * hm->squareSize); const uchar* normal = hm->GetNormal(x, y); Vector3 normv((2 * (int)normal[0] - 256)/255.0f, (2 * (int)normal[1] - 256)/255.0f, (2 * (int)normal[2] - 256)/255.0f); wp.ANormalize(); float dot = wp.dot(normv); if(dot < 0.0f) dot = 0.0f; if(dot > 1.0f) dot = 1.0f; dot *= lightMap[(y*shadowW + x) / shadowScale] * (1.0f / 255.0f); shading[y*w + x] += l->color * dot; } } } delete[] lightMap; glGenTextures(1, &shadingTex); glBindTexture (GL_TEXTURE_2D, shadingTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); uchar* shadingTexData = new uchar[w*w*4]; for (int y = 0; y < w; y++) { for (int x = 0; x < w; x++) { shadingTexData[(y*w + x) * 4 + 0] = (uchar)(min(1.0f, shading[y*w + x].x) * 255); shadingTexData[(y*w + x) * 4 + 1] = (uchar)(min(1.0f, shading[y*w + x].y) * 255); shadingTexData[(y*w + x) * 4 + 2] = (uchar)(min(1.0f, shading[y*w + x].z) * 255); shadingTexData[(y*w + x) * 4 + 3] = CReadMap::EncodeHeight(centerhm[w*y + x]); } } SaveImage ("lightmap.png", 4, IL_UNSIGNED_BYTE, w, w, shadingTexData); glBuildMipmaps(GL_TEXTURE_2D, 4, w, w, GL_RGBA, GL_UNSIGNED_BYTE, shadingTexData); delete[] shadingTexData; id = shadingTex; delete[] shading; delete[] centerhm; const spring_duration numTicks = spring_gettime() - startTicks; LOG("Lightmap generation: %2.3f seconds", spring_tomsecs(numTicks) * 0.001f); }