Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

08.05.2009, 18:31

Terrain bemalen

Hi Spieleprogrammierer! Ich bräuchte einmal eure Hilfe.

Ich möchte das man auf meinem Terrain zeichnen kann, dafür habe ich mich fürs Texture-Splatting entschieden. In meinem Shader rechne ich die Pixel So zusammen:

C-/C++-Quelltext

1
2
3
4
5
6
float4 map = tex2D(sMap, In.Texcoord);
    
colmap += tex2D(sRed, In.Texcoord) * map.r;
colmap += tex2D(sGreen, In.Texcoord) * map.g;
colmap += tex2D(sBlue, In.Texcoord) * map.b;
colmap += tex2D(sAlpha, In.Texcoord) * map.a;


Ein PIxel in der Colormap setze ich folgendermaßen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
unsigned int color = ((unsigned int*)lockedRect.Bits)[y * mWidth + x];

                            float a = intensity * 255.0f * pen->Intensity;

                            Vector3 rgb = Vector3Normalize(Vector3(static_cast<float>(GetR(color)),
                                                                   static_cast<float>(GetG(color)),
                                                                   static_cast<float>(GetB(color)))) * (255.0f - a);

                            if(a > GetA(color))
                                ((unsigned int*)lockedRect.Bits)[y * mWidth + x] = SetARGB(Vector4(a, rgb.X, rgb.Y, rgb.Z));


Zuvor Locke ich den Texture Buffer und gehe alle Pixel durch, und dann anhand der deferenz zum mittelpunkt der "Stift Position" bestimme ich die intensität, sodass ein sanfter übergang zwischen den texturen entsteht.

Als erstes hole ich mir den gewünschten Pixel aus dem Buffer und anschließend berechne ich die intensität dieses Pixels, in diesem fall nur des Alpha Kanals. Danach erstelle ich einen Vector3 und fülle ihn mit den R G und B Werten des Pixels, und schließlich Normalisiere ich ihn und multiplitziere ihn mit der deffernez des Alpha Werts und 255. Danach teste ich ob der neue Alpha Wert auch größer ist als der alte, und wenn dies zutrifft, fülle ich den Buffer mit diesem Pixel.

Soweit funktioniert das auch sehr gut, solange sich nur 2 Texturen überschneiden, wenn sich aber 3 Texturen überschneiden wird diese stelle um so mehr aufgehellt, das man dies sher stark sehen kann:

http://www9.picfront.org/picture/BTTBEbBkFsi/img/0000012004.png
(Das Bild ist ein wenig groß, damit man den Fehler auch genau sehen kann)

Ich habe die stellen wo sich 3 Texturen überschneiden Rot makiert, und die wo nur 2 grün.

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

2

08.05.2009, 20:04

Du musst gewährleisten, dass die Summe aller 4 Farbkanäle immer 1 ergibt. Ansonsten wirds zwangsläufig mal heller mal dunkler, je nachdem "wieviel Textur" gesampelt wird.

Das könntest du ausgleichen, indem du jede Farbe mit der Summe seiner Kanäle teilst. (zumindest ist das gerade die erstbeste Idee meinerseits ^^)

3

08.05.2009, 20:18

Zitat von »"Wümpftlbrümpftl"«

Du musst gewährleisten, dass die Summe aller 4 Farbkanäle immer 1 ergibt. Ansonsten wirds zwangsläufig mal heller mal dunkler, je nachdem "wieviel Textur" gesampelt wird.

Das könntest du ausgleichen, indem du jede Farbe mit der Summe seiner Kanäle teilst. (zumindest ist das gerade die erstbeste Idee meinerseits ^^)

Ich würd das ganze noch ein bischen treiben, und wie bei der vektornormalisierung arbeiten: sieh die farben als 4D-vektor.
bilde den durchschnitt aus der länge der ausgangsfarben, und bringe die endfarbe auf diese länge (normalisieren + komponentenweises multiplizieren).

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

4

08.05.2009, 20:24

Normalisieren führt aber wohl doch wieder zu Farbunterschieden?

Es ist ja erwünscht, dass sich die Summe 1 aus allen Texturanteilen ergibt, damit immer gleich viel Texturgewichtung vorherscht und so eben nicht einmal hellere und einmal dunklere Farben rauskommen. Wenn man jetzt normalisiert, ist die Summe ja nicht mehr 1. Ist ja schließlich auch kein echter Vektor.

Oder überseh ich da was?

5

08.05.2009, 20:52

Im prinziep mache ich das schon so:

C-/C++-Quelltext

1
2
3
Vector3 rgb = Vector3Normalize(Vector3(static_cast<float>(GetR(color)),
                                                                   static_cast<float>(GetG(color)),
                                                                   static_cast<float>(GetB(color)))) * (255.0f - a); 


Am die endfarbe sollte dann eigentlich immer eine länge von 255 haben, da ich wenn der Wert a 150 hat, dann rechne ich den normalisierten Vector3 * 105, wodurch alle zusammen addiert dann 255 ergeben.

Ich habe nun nochmal am ende den Vector4 Normalisiert, es ist zwar nicht mehr heller, aber sieht nicht mehr so schön aus.

Im prinziep ist es leicht um zu setzen, jedoch möchte ich, wenn der benutzer des Programms eine intensität von 1 angiebt, auch an dieser stelle NUR diese Textur zu sehen ist, und wenn man 0.5 angiebt, dann ist auch die Hälfte der Textur zu sehen, und die restlichen 3 teilen sich halt den rest was übrig bleibt.

6

08.05.2009, 21:06

Zitat von »"Wümpftlbrümpftl"«

Oder überseh ich da was?

du übersiehst, das es z.B. auch stellen gaben kann, die in beiden texturen schwarz sind, und in der endtextur also auch schwarz sein sollen. dementsprechend muss man ncit auf komponentensumme/länge/whatever von 1 gehen, sodnern auf die, des (gewichteten) durchschnitts (ok, das ist jetz blöd ausgedrückt) der ausgangsfarben bringen.

7

08.05.2009, 22:39

Anscheinend steckt in meinem Code ein großer denk fehler, ich wollte das ganze nun mal ohne Normalisieren bewerkstelligen. Aber so wie ich mir das gedacht habe ist das exact das selbe wie oben.

Ich habe das ganze nun so zu sagen mit dem Dreisatz gelöst:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
switch(pen->Channel)
                    {
                        case PenChannel::Alpha:
                        {
                            pixelColor.X += a;

                            pixelColor.Y -= (float)GetR(color) / 255.0f * a;
                            pixelColor.Z -= (float)GetG(color) / 255.0f * a;
                            pixelColor.W -= (float)GetB(color) / 255.0f * a;
                            break;
                        }
                        case PenChannel::Red:
                        {
                            pixelColor.Y += a;

                            pixelColor.X -= (float)GetA(color) / 255.0f * a;
                            pixelColor.Z -= (float)GetG(color) / 255.0f * a;
                            pixelColor.W -= (float)GetB(color) / 255.0f * a;
                            break;
                        }
                        case PenChannel::Green:
                        {
                            pixelColor.Z += a;

                            pixelColor.X -= (float)GetA(color) / 255.0f * a;
                            pixelColor.Y -= (float)GetR(color) / 255.0f * a;
                            pixelColor.W -= (float)GetB(color) / 255.0f * a;
                            break;
                        }
                        case PenChannel::Blue:
                        {
                            pixelColor.W += a;

                            pixelColor.X -= (float)GetA(color) / 255.0f * a;
                            pixelColor.Y -= (float)GetR(color) / 255.0f * a;
                            pixelColor.Z -= (float)GetG(color) / 255.0f * a;
                            break;
                        }
                    }

                    if(pixelColor.X > 255.0f) pixelColor.X = 255.0f; else if(pixelColor.X < 0.0f) pixelColor.X = 0.0f;
                    if(pixelColor.Y > 255.0f) pixelColor.Y = 255.0f; else if(pixelColor.Y < 0.0f) pixelColor.Y = 0.0f;
                    if(pixelColor.Z > 255.0f) pixelColor.Z = 255.0f; else if(pixelColor.Z < 0.0f) pixelColor.Z = 0.0f;
                    if(pixelColor.W > 255.0f) pixelColor.W = 255.0f; else if(pixelColor.W < 0.0f) pixelColor.W = 0.0f;


Hier mal ein Screenshot:

http://picfront.de/d/sAIkYkO3tO/0000012006.png

Die übergänge sind nun sehr gleichmäßig, jeodch wenn ich sehr lange an einer stelle die Maus lasse, dann werden die render schwarz, ich vermute das liegt daran das ich nun anstatt dem Kanal einen Festen Wert gebe, nun den Wert addiere.

Werbeanzeige