mercator 0.4.0
A terrain generation library for the Worldforge system.
GrassShader.cpp
1// This file may be redistributed and modified only under the terms of
2// the GNU General Public License (See COPYING for details).
3// Copyright (C) 2003 Alistair Riddoch
4
5#ifdef HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#include "GrassShader.h"
10
11#include "Segment.h"
12#include "Surface.h"
13
14#include <cmath>
15
16#include <cassert>
17
18namespace Mercator {
19
20const std::string GrassShader::key_lowThreshold("lowThreshold");
21const std::string GrassShader::key_highThreshold("highThreshold");
22const std::string GrassShader::key_cutoff("cutoff");
23const std::string GrassShader::key_intercept("intercept");
24
25const float GrassShader::default_lowThreshold = 1.f;
26const float GrassShader::default_highThreshold = 20.f;
27const float GrassShader::default_cutoff = 1.f;
28const float GrassShader::default_intercept = 2.f;
29
30GrassShader::GrassShader(float lowThreshold, float highThreshold,
31 float cutoff, float intercept) :
32 m_lowThreshold(lowThreshold), m_highThreshold(highThreshold),
33 m_cutoff(cutoff), m_intercept(intercept)
34{
35}
36
38 m_lowThreshold(default_lowThreshold),
39 m_highThreshold(default_highThreshold),
40 m_cutoff(default_cutoff),
41 m_intercept(default_intercept)
42{
43 auto I = params.find(key_lowThreshold);
44 auto Iend = params.end();
45 if (I != Iend) {
46 m_lowThreshold = I->second;
47 }
48 I = params.find(key_highThreshold);
49 if (I != Iend) {
50 m_highThreshold = I->second;
51 }
52 I = params.find(key_cutoff);
53 if (I != Iend) {
54 m_cutoff = I->second;
55 }
56 I = params.find(key_intercept);
57 if (I != Iend) {
58 m_intercept = I->second;
59 }
60
61}
62
63GrassShader::~GrassShader() = default;
64
65inline ColorT GrassShader::slopeToAlpha(float height, float slope) const
66{
67 if ((height < m_lowThreshold) ||
68 (height > m_highThreshold) ||
69 (slope > m_intercept)) {
70 return colorMin;
71 } else if (slope < m_cutoff) {
72 return colorMax;
73 } else {
74 return (ColorT)(colorMax * ((slope - m_cutoff) / (m_intercept - m_cutoff)));
75 }
76}
77
79{
80 if ((s.getMin() < m_highThreshold) &&
81 (s.getMax() > m_lowThreshold)) {
82 return true;
83 } else {
84 return false;
85 }
86}
87
89{
90 unsigned int channels = s.getChannels();
91 assert(channels > 0);
92 unsigned int chanAlpha = channels - 1;
93 const Segment & seg = s.getSegment();
94 ColorT * data = s.getData();
95 const float * height_data = seg.getPoints();
96 if (height_data == nullptr) {
97 std::cerr << "WARNING: Mercator: Attempting to shade empty segment."
98 << std::endl << std::flush;
99 return;
100 }
101 int size = seg.getSize();
102 int res = seg.getResolution();
103
104 unsigned int data_count = size * size * channels;
105 for (unsigned int i = 0; i < data_count; ++i) {
106 data[i] = colorMax;
107 }
108
109 // Deal with corner points
110 s(0, 0, chanAlpha) = slopeToAlpha(seg.get(0,0), 0.f);
111 s(res, 0, chanAlpha) = slopeToAlpha(seg.get(res,0), 0.f);
112 s(0, res, chanAlpha) = slopeToAlpha(seg.get(0,res), 0.f);
113 s(res, res, chanAlpha) = slopeToAlpha(seg.get(res,res), 0.f);
114
115 for (int i = 1; i < res; ++i) {
116 float height = seg.get(i, 0);
117 float avgSlope = (std::fabs(seg.get(i - 1, 0) - height) +
118 std::fabs(seg.get(i + 1, 0) - height)) / 2.f;
119 s(i, 0, chanAlpha) = slopeToAlpha(height, avgSlope);
120
121 height = seg.get(i, res);
122 avgSlope = (std::fabs(seg.get(i - 1, res) - height) +
123 std::fabs(seg.get(i + 1, res) - height)) / 2.f;
124 s(i, res, chanAlpha) = slopeToAlpha(height, avgSlope);
125
126 height = seg.get(0, i);
127 avgSlope = (std::fabs(seg.get(0, i - 1) - height) +
128 std::fabs(seg.get(0, i + 1) - height)) / 2.f;
129 s(0, i, chanAlpha) = slopeToAlpha(height, avgSlope);
130
131 height = seg.get(res, i);
132 avgSlope = (std::fabs(seg.get(res, i - 1) - height) +
133 std::fabs(seg.get(res, i + 1) - height)) / 2.f;
134 s(res, i, chanAlpha) = slopeToAlpha(height, avgSlope);
135 for (int j = 1; j < res; ++j) {
136 height = seg.get(i, j);
137 avgSlope = (std::fabs(seg.get(i + 1, j ) - height) +
138 std::fabs(seg.get(i , j + 1) - height) +
139 std::fabs(seg.get(i - 1, j ) - height) +
140 std::fabs(seg.get(i , j - 1) - height)) / 4.f;
141 s(i, j, chanAlpha) = slopeToAlpha(height, avgSlope);
142 }
143 }
144}
145
146} // namespace Mercator
DataType * getData()
Accessor for a pointer to buffer containing data values.
Definition: Buffer.h:63
unsigned int getChannels() const
Accessor for the number of data values per height point.
Definition: Buffer.h:58
static const std::string key_lowThreshold
Key string used when specifying the low threshold parameter.
Definition: GrassShader.h:70
static const std::string key_cutoff
Key string used when specifying the cutoff parameter.
Definition: GrassShader.h:74
static const float default_lowThreshold
Default level above which the shader renders.
Definition: GrassShader.h:79
void shade(Surface &) const override
Populate a Surface with data.
Definition: GrassShader.cpp:88
GrassShader(float lowThreshold=default_lowThreshold, float highThreshold=default_highThreshold, float cutoff=default_cutoff, float intercept=default_intercept)
Constructor.
Definition: GrassShader.cpp:30
static const float default_highThreshold
Default level below which the shader renders.
Definition: GrassShader.h:81
bool checkIntersect(const Segment &) const override
Check whether this Shader has any effect on the given Segment.
Definition: GrassShader.cpp:78
static const float default_intercept
Default slope steeper than which no grass grows.
Definition: GrassShader.h:85
static const std::string key_highThreshold
Key string used when specifying the high threshold parameter.
Definition: GrassShader.h:72
static const float default_cutoff
Default slope below which grass is opaque.
Definition: GrassShader.h:83
static const std::string key_intercept
Key string used when specifying the intercept parameter.
Definition: GrassShader.h:76
Class storing heightfield and other data for a single fixed size square area of terrain defined by fo...
Definition: Segment.h:37
int getResolution() const
Accessor for resolution of this segment.
Definition: Segment.h:83
int getSize() const
Accessor for array size of this segment.
Definition: Segment.h:88
float getMin() const
Accessor for the minimum height value in this Segment.
Definition: Segment.h:191
float getMax() const
Accessor for the maximum height value in this Segment.
Definition: Segment.h:189
const float * getPoints() const
Accessor for buffer containing height points.
Definition: Segment.h:143
float get(int x, int z) const
Get the height at a relative integer position in the Segment.
Definition: Segment.h:173
std::map< std::string, float > Parameters
STL map of parameter values for a shader constructor.
Definition: Shader.h:59
Data store for terrain surface data.
Definition: Surface.h:23
const Segment & getSegment() const
Accessor for the terrain height segment this surface is associated with.
Definition: Surface.h:37