tak dobrze tylko że to tego cieniowania jak będą dodawane piksele z tła bo czyta tło i myślę że to troche głupio będzie wyglądać, to niech już będzie bez Smooth
obrót tekstury 2D softwarowy
- Rejestracja: dni
- Ostatnio: dni
- Postów: 678
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Poznań
- Postów: 526
Możesz zawsze zapisywać obraz najpierw do tablicy, potem przelatujesz tablicę i robiśz średnią z pikseli omijając puste piksele w taki sposób że jak piksel jest pusty to nie dodawaj do średniej
- Rejestracja: dni
- Ostatnio: dni
- Postów: 678
chyba że tak, ja też myślałem czy można pobrać tablice z tablicy z obrazem a potem ten pobrany obraz obracać po staremu jak pisaliśmy obrót tekstury całej, czy wtedy nie było by straty na jakości grafiki? bo powinno nie być starty bo już sprawdzaliśmy i było ok na 100 %
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Poznań
- Postów: 526
Albo można zrobić tak, że zapisujesz obraz do tablicy i liczysz średnią z sąsiednich pikseli dla wszystkich pustych pikseli
- Rejestracja: dni
- Ostatnio: dni
- Postów: 678
już mam ale nie sprawdzałem, jeśli mnie zrozumiesz po tym kodzie o co chodzi mi a zauważysz błąd to popraw:
unsigned char* GetDataFragmentTexture(int xs, int ys, int xe, int ye, int nr,int &width,int &height)
{
int w = bi[nr].w;
int h = bi[nr].h;
int x = xe - xs;
int y = ye - ys;
int xpos = 0;
int ypos = 0;
width = x;
height = y;
unsigned char* gdata = new unsigned char[x * y * 3];
for (int py = ys; py < ye; py += 1)
{
for (int px = xs; px < xe; px += 1)
{
int pis = (xpos * 3 + ypos * y * 3);
int index = (px * 3 + (h - py) * w * 3);
gdata[pis] = bi[nr].bitmapData[index];
gdata[pis + 1] = bi[nr].bitmapData[index + 1];
gdata[pis + 2] = bi[nr].bitmapData[index + 2];
xpos += 1;
if (xpos == x)
xpos = 0;
}
ypos += 1;
}
return gdata;
}
potem u siebie w swojej funkcji obrotu zamiast tego:
int w = bi[nr].w;
int h = bi[nr].h;
int bpp = 3;
const unsigned char* src = bi[nr].bitmapData;
wstaw to tej pierwszej funkcji z obrotem gdzie nie było utraty na jakości grafiki
int w,h;
int bpp=3;
const unsigned char* src=GetDataFragmentTexture(xs,ys,xe,ye,nr,w,h);
- Rejestracja: dni
- Ostatnio: dni
- Postów: 678
skończone i działa , są dwie fukcje
unsigned char* GetDataFragmentTexture(int xs, int ys, int xe, int ye, int nr,int &width,int &height)
{
int w = bi[nr].w;
int h = bi[nr].h;
int x = xe - xs;
int y = ye - ys;
int xpos = 0;
int ypos = 0;
width = x;
height = y;
unsigned char* gdata = new unsigned char[x * y * 3];
for (int py = ys; py < ye; py += 1)
{
for (int px = xs; px < xe; px += 1)
{
int pis = (xpos * 3 + ypos * y * 3);
int index = (px * 3 + (h - py) * w * 3);
gdata[pis] = bi[nr].bitmapData[index];
gdata[pis + 1] = bi[nr].bitmapData[index + 1];
gdata[pis + 2] = bi[nr].bitmapData[index + 2];
xpos += 1;
if (xpos == x)
xpos = 0;
}
ypos += 1;
}
return gdata;
}
void DrawObiectImageCoordRotate(int x, int y, int nr, float angleDeg, int xs, int ys, int xe, int ye)
{
int w, h, bpp;
bpp = 3;
const unsigned char* src = GetDataFragmentTexture(xs, ys, xe, ye, nr, w, h);
float ang = angleDeg * 3.14159265358979323846f / 180.f;
float c = std::cos(ang);
float s = std::sin(ang);
// nowa obwiednia
int newW = (int)std::ceil(std::fabs(w * c) + std::fabs(h * s));
int newH = (int)std::ceil(std::fabs(w * s) + std::fabs(h * c));
// środki
float cx = (w - 1) * 0.5f;
float cy = (h - 1) * 0.5f;
float ncx = (newW - 1) * 0.5f;
float ncy = (newH - 1) * 0.5f;
// przesunięcie pozycji docelowej, aby obraz był wycentrowany względem (x,y)
int offX = (int)std::round(ncx - cx);
int offY = (int)std::round(ncy - cy);
for (int py = 0; py < newH; ++py)
{
for (int px = 0; px < newW; ++px)
{
// współrzędne dst względem środka NOWEJ ramki
float dx = px - ncx;
float dy = py - ncy;
// mapowanie dst -> src (obrót o -ang)
float srcX = dx * c + dy * s + cx;
float srcY = -dx * s + dy * c + cy;
int ix = (int)std::floor(srcX + 0.5f);
int iy = (int)std::floor(srcY + 0.5f);
if (ix >= 0 && iy >= 0 && ix < w && iy < h)
{
int base = (iy * w + ix) * bpp; // jeśli BMP bottom-up: (h-1-iy)*w + ix
unsigned char r = src[base + 0];
unsigned char g = src[base + 1];
unsigned char b = src[base + 2];
// jeśli BGR -> zamień r<->b
Color3iT(r, g, b);
PutPixelT(x + px - offX, y + py - offY);
}
// else: piksel poza źródłem — zostaw tło/nie rysuj
}
}
}
i nie ma utraty na jakości grafiki tak jak Ci podał tBane chatgpt. tą pierwszą wersje
DrawConsole.rar
- Rejestracja: dni
- Ostatnio: dni
wilkwielki napisał(a):
teraz działa ale trzeba dodać dodatkowe wartości na nową szerokość i wysokość bo jest obcięte ale działa
To dlatego że trzeba iterować po x i y docelowego obrazka, i wyliczać pozycję piksela źródłowego (stosując obrót w odwrotną stronę).
Podejście "naiwne" – iterowanie po pikselach źródłowych i wyliczanie docelowej pozycji każdego piksela – da słaby jakościowo wynik.
Nowy rozmiar (żeby nic nie obcięło) to już trzeba by sobie osobno wyliczyć.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 6959
Przydałoby się ten software'owy renderer napisać jak należy.
Tak jak OpenGL, obracasz tylko rogi quada i renderujesz piksele tekstury na podstawie UV przypisanych do poszczególnych rogów.
Możesz stosować przy tym interpolację. Patrz ile w GIMPie jest wariantów interpolacji przy obracaniu:

- Rejestracja: dni
- Ostatnio: dni
- Postów: 678
powiem tak, algorytm który podał tBane z moją podpinką GetDataFragmentTexture jest perfekcyjny na 100 % ponieważ nie ma straty na jakości grafiki pod czas rotacji pikseli, interpolacji nie mogę zrobić ponieważ w efekcie wyjdzie filtrowanie z przypadku, tak nie ma być po to starta na jakości grafiki, więc lepiej już się nie da ..